Oracle Redo Log 機制 小結(轉載)
Oracle 的Redo 機制DB的一個重要機制,理解這個機制對DBA來說也是非常重要,之前的Blog里也林林散散的寫了一些,前些日子看老白日記里也有說明,所以結合老白日記里的內容,對oracle 的整個Redo log 機制重新整理一下。
一.Redo log 說明
Oracle 的Online redo log 是為確保已經提交的事務不會丟失而建立的一個機制。 因為這種健全的機制,才能讓我們在數據庫crash時,恢復數據,保證數據不丟失。
1.1 恢復分類
恢復分兩種:
(1) Crash recovery
(2) Media recovery
這兩種的具體說明,參考:
Oracle 實例恢復時 前滾(roll forward) 后滾(rollback) 問題
http://blog.csdn.net/tianlesoftware/article/details/6286330
這兩種的區別是:
(1) Crash Recovery 是在啟動時DB 自動完成,而MediaRecovery 需要DBA 手工的完成。
(2) Crash Recovery 使用online redo log,Media Recovery 使用archived log 和 online redo log。
(3) Media Recovery 可能還需要從備份中Restore datafile。
1.2 Crash Recovery 過程
當數據庫突然崩潰,而還沒有來得及將buffer cache里的臟數據塊刷新到數據文件里,同時在實例崩潰時正在運行著的事務被突然中斷,則事務為中間狀態,也就是既沒有提交也沒有回滾。這時數據文件里的內容不能體現實例崩潰時的狀態。這樣關閉的數據庫是不一致的。
下次啟動實例時,Oracle會由SMON進程自動進行實例恢復。實例啟動時,SMON進程會去檢查控制文件中所記錄的、每個在線的、可讀寫的數據文件的END SCN號。
數據庫正常運行過程中,該END SCN號始終為NULL,而當數據庫正常關閉時,會進行完全檢查點,并將檢查點SCN號更新該字段。
而崩潰時,Oracle還來不及更新該字段,則該字段仍然為NULL。當SMON進程發現該字段為空時,就知道實例在上次沒有正常關閉,于是由SMON進程就開始進行實例恢復了。
1.2.1 前滾
SMON進程進行實例恢復時,會從控制文件中獲得檢查點位置。于是,SMON進程到聯機日志文件中,找到該檢查點位置,然后從該檢查點位置開始往下,應用所有的重做條目,從而在buffer cache里又恢復了實例崩潰那個時間點的狀態。這個過程叫做前滾,前滾完畢以后,buffer cache里既有崩潰時已經提交還沒有寫入數據文件的臟數據塊,也還有事務被突然終止,而導致的既沒有提交又沒有回滾的事務所弄臟的數據塊。
1.2.2 回滾
前滾一旦完畢,SMON進程立即打開數據庫。但是,這時的數據庫中還含有那些中間狀態的、既沒有提交又沒有回滾的臟塊,這種臟塊是不能存在于數據庫中的,因為它們并沒有被提交,必須被回滾。打開數據庫以后,SMON進程會在后臺進行回滾。
有時,數據庫打開以后,SMON進程還沒來得及回滾這些中間狀態的數據塊時,就有用戶進程發出讀取這些數據塊的請求。這時,服務器進程在將這些塊返回給用戶之前,由服務器進程負責進行回滾,回滾完畢后,將數據塊的內容返回給用戶。
總之,Crash Recovery時,數據庫打開會占用比正常關閉更長的時間。
1.2.3 必須先前滾,在回滾
回滾段實際上也是以回滾表空間的形式存在的,既然是表空間,那么肯定就有對應的數據文件,同時在buffer cache 中就會存在映像塊,這一點和其他表空間的數據文件相同。
當發生DML操作時,既要生成REDO(針對DML操作本身的REDO Entry)也要生成UNDO(用于回滾該DML操作,記錄在UNDO表空間中),但是既然UNDO信息也是使用回滾表空間來存放的,那么該DML操作對應的UNDO信息(在BUFFER CACHE生成對應中的UNDO BLOCK)就會首先生成其對應的REDO信息(UNDO BLOCK's REDO Entry)并寫入Log Buffer中。
這樣做的原因是因為Buffer Cache中的有關UNDO表空間的塊也可能因為數據庫故障而丟失,為了保障在下一次啟動時能夠順利進行回滾,首先就必須使用REDO日志來恢復UNDO段(實際上是先回復Buffer Cache中的臟數據塊,然后由Checkpoint寫入UNDO段中),在數據庫OPEN以后再使用UNDO信息來進行回滾,達到一致性的目的。
生成完UNDO BLOCK's REDO Entry后才輪到該DML語句對應的REDO Entry,最后再修改Buffer Cache中的Block,該Block同時變為臟數據塊。
實際上,簡單點說REDO的作用就是記錄所有的數據庫更改,包括UNDO表空間在內。
1.2.4 Crash Recovery 再細分
Crash Recovery 可以在細分成兩種:
(1) 實例恢復(InstanceRecovery)
(2) 崩潰恢復(CrashRecovery)
InstanceRecovery與CrashRecovery是存在區別的:針對單實例(singleinstance)或者RAC中所有節點全部崩潰后的恢復,我們稱之為Crash Recovery。 而對于RAC中的某一個節點失敗,存活節點(surviving instance)試圖對失敗節點線程上redo做應用的情況,我們稱之為InstanceRecovery。
不管是Instance Recovery還是Crash Recovery,都由2個部分組成:cache recovery和transaction recovery。
根據官方文檔的介紹,Cache Recovery也叫Rolling Forward(前滾);而Transaction Recovery也叫Rolling Back(回滾)。
更多內容參考:
http://blog.csdn.net/tianlesoftware/article/details/6547891
Oracle 實例恢復時 前滾(roll forward) 后滾(rollback) 問題
http://blog.csdn.net/tianlesoftware/article/details/6286330
1.3 Redo log 說明
REDO LOG 的數據是按照THREAD 來組織的,對于單實例系統來說,只有一個THREAD,對于RAC 系統來說,可能存在多個THREAD,每個數據庫實例擁有一組獨立的REDO LOG 文件,擁有獨立的LOG BUFFER,某個實例的變化會被獨立的記錄到一個THREAD 的REDO LOG 文件中。
對于單實例的系統,實例恢復(Instance Recovery)一般是在數據庫實例異常故障后數據庫重啟時進行,當數據庫執行了SHUTDOWN ABORT 或者由于操作系統、主機等原因宕機重啟后,在ALTER DATABASE OPEN 的時候,就會自動做實例恢復。
在RAC 環境中,如果某個實例宕了,或者實例將會接管,替宕掉的實例做實例恢復。除非是所有的實例都宕了,這樣的話,第一個執行ALTER DATABASE OPEN 的實例將會做實例恢復。這也是REDO LOG 是實例私有的組件,但是REDO LOG 文件必須存放在共享存儲上的原因。
Oracle 數據庫的CACHE 機制是以性能為導向的,CACHE 機制應該最大限度的提高數據庫的性能,因此CACHE 被寫入數據文件總是盡可能的推遲。這種機制大大提高了數據庫的性能,但是當實例出現故障時,可能出現一些問題。
首先是在實例故障時,可能某些事物對數據文件的修改并沒有完全寫入磁盤,可能磁盤文件中丟失了某些已經提交事務對數據文件的修改信息。
其次是可能某些還沒有提交的事務對數據文件的修改已經被寫入磁盤文件了。也有可能某個原子變更的部分數據已經被寫入文件,而部分數據還沒有被寫入磁盤文件。
實例恢復就是要通過ONLINE REDO LOG 文件中記錄的信息,自動的完成上述數據的修復工作。這個過程是完全自動的,不需要人工干預。
1.3.1 如何確保已經提交的事務不會丟失?
解決這個問題比較簡單,Oracle 有一個機制,叫做Log-Force-at-Commit,就是說,在事務提交的時候,和這個事務相關的REDO LOG 數據,包括COMMIT 記錄,都必須 從LOG BUFFER 中寫入REDO LOG 文件,此時事務提交成功的信號才能發送給用戶進程。通過這個機制,可以確保哪怕這個已經提交的事務中的部分BUFFER CACHE 還沒有被寫入數據文件,就發生了實例故障,在做實例恢復的時候,也可以通過REDO LOG 的信息,將不一致的數據前滾。
1.3.2 如何在數據庫性能和實例恢復所需要的時間上做出平衡?
既確保數據庫性能不會下降,又保證實例恢復的快速,解決這個問題,oracle是通過checkpoint 機制來實現的。
Oracle 數據庫中,對BUFFER CAHCE 的修改操作是前臺進程完成的,但是前臺進程只負責將數據塊從數據文件中讀到BUFFERCACHE 中,不負責BUFFERCACHE 寫入數據文件。BUFFERCACHE 寫入數據文件的操作是由后臺進程DBWR 來完成的。DBWR 可以根據系統的負載情況以及數據塊是否被其他進程使用來將一部分數據塊回寫到數據文件中。這種機制下,某個數據塊被寫回文件的時間可能具有一定的隨機性的,有些先修改的數據塊可能比較晚才被寫入數據文件。
而CHECKPOINT 機制就是對這個機制的一個有效的補充,CHECKPOINT 發生的時候,CKPT 進程會要求DBWR 進程將某個SCN 以前的所有被修改的塊都被寫回數據文件。這樣一旦這次CHECKPOINT 完成后,這個SCN 前的所有數據變更都已經存盤,如果之后發生了實例故障,那么做實例恢復的時候,只需要沖這次CHECKPOINT 已經完成后的變化量開始就行了,CHECKPOINT 之前的變化就不需要再去考慮了。
1.3.3 有沒有可能數據文件中的變化已經寫盤,但是REDO LOG 信息還在LOG BUFFER 中,沒有寫入REDO LOG 呢?
這里引入一個名詞:Write-Ahead-Log,就是日志寫入優先。日志寫入優先包含兩方面的算法:
第一個方面是,當某個BUFFER CACHE 的修改的變化矢量還沒有寫入REDO LOG 文件之前,這個修改后的BUFFER CACHE 的數據不允許被寫入數據文件,這樣就確保了再數據文件中不可能包含未在REDO LOG 文件中記錄的變化;
第二個方面是,當對某個數據的UNDO 信息的變化矢量沒有被寫入REDOLOG 之前,這個BUFFERCACHE的修改不能被寫入數據文件。
相關鏈接:
http://blog.csdn.net/tianlesoftware/article/details/5251916
http://blog.csdn.net/tianlesoftware/article/details/6700085
二.LOG BUFFER 和LGWR
2.1 Redo Log 說明
REDO LOG是順序寫的文件,每次寫入的數據量很小,TEMP文件雖然也就有部分順序讀寫的特點,但是TEMP每次讀寫的數據量較大,和REDO 的特性不同。UNDO是典型的隨機讀寫的文件,索引更是以單塊讀為主的操作。
REDO LOG 的產生十分頻繁,幾乎每秒鐘都有幾百K 到幾M 的RED LOG 產生,甚至某些大型數據庫每秒鐘產生的REDO LOG 量達到了10M 以上。不過前臺進程每次產生的REDO量卻不大,一般在幾百字節到幾K,而一般一個事務產生的REDO 量也不過幾K到幾十K。
基于REDO 產生的這個特點,如果每次REDO產生后就必須寫入REDOLOG 文件,那么就會存在兩個問題,一個是REDO LOG 文件寫入的頻率過高,會導致REDO LOG文件的IO 存在問題,第二個是如果由前臺進程來完成REDO LOG 的寫入,那么會導致大量并發的前臺進程產生REDO LOG 文件的爭用。
為了解決這兩個問題,Oracle 在REDO LOG 機制中引入了LGWR 后臺進程和LOGBUFFER。
LOG BUFFER 是Oracle 用來緩存前臺進程產生的REDO LOG 信息的,有了LOG BUFFER,前臺進程就可以將產生的REDO LOG 信息寫入LOG BUFFER,而不需要直接寫入REDO LOG 文件,這樣就大大提高了REDO LOG 產生和保存的時間,從而提高數據庫在高并發情況下的性能。既然前臺進程不將REDOLOG 信息寫入REDO LOG 文件了,那么就必須要有一個后臺進程來完成這個工作。這個后臺進程就是LGWR,LGWR 進程的主要工作就是將LOG BUFFER 中的數據批量寫入到REDO LOG 文件中。對于Oracle 數據庫中,只要對數據庫的改變寫入到REDO LOG 文件中了,那么就可以確保相關的事務不會丟失了。
引入LOG BUFFER 后,提高了整個數據庫RDMBS 寫日志的性能,但是如何確保一個已經提交的事務確確實實的被保存在數據庫中,不會因為之后數據庫發生故障而丟失呢?實際上在前面兩節中我們介紹的REDO LOG 的一些基本的算法確保了這一點。
首先WRITE AHEAD LOG 協議確保了只要保存到REDO LOG 文件中的數據庫變化一定能夠被重演,不會丟失,也不會產生二義性。其次是在事務提交的時候,會產生一個COMMIT 的CV,這個CV 被寫入LOG BUFFER 后,前臺進程會發出一個信號,要求LGWR 將和這個事務相關的REDO LOG 信息寫入到REDO LOG 文件中,只有這個事務相關的REDO LOG 信息已經確確實實被寫入REDO LOG 文件的時候,前臺進程才會向客戶端發出事務提交成功的消息,這樣一個事務才算是被提交完成了。在這個協議下,只要客戶端收到了提交完成的消息,那么可以確保,該事務已經存盤,不會丟失了。
LGWR 會繞過操作系統的緩沖,直接寫入數據文件中,以確保REDO LOG 的信息不會因為操作系統出現故障(比如宕機)而丟失要求確保寫入REDO LOG 文件的數據。
實際上,雖然Oracle 數據庫使用了繞過緩沖直接寫REDO LOG 文件的方法,以避免操作系統故障導致的數據丟失,不過我們還是無法確保這些數據已經確確實實被寫到了物理磁盤上。因為我們RDBMS 使用的絕大多數存儲系統都是帶有寫緩沖的,寫緩沖可以有效的提高存儲系統寫性能,不過也帶來了另外的一個問題,就是說一旦存儲出現故障,可能會導致REDO LOG 的信息丟失,甚至導致REDO LOG 出現嚴重損壞。存儲故障的概率較小,不過這種小概率事件一旦發生還是會導致一些數據庫事務的丟失,因此雖然Oracle 的內部算法可以確保一旦事務提交成功,事務就確認被保存完畢了,不過還是可能出現提交成功的事務丟失的現象。
實際上,Oracle 在設計REDO LOG 文件的時候,已經最大限度的考慮了REDO LOG 文件的安全性,REDO LOG 文件的BLOCK SIZE 和數據庫的BLOCK SIZE 是完全不同的,REDO LOG 文件的BLOCK SIZE 是和操作系統的IO BLOCK SZIE 完全相同的,這種設計確保了一個REDO LOG BLOCK 是在一次物理IO 中同時寫入的,因此REDOLOG BLOCK 不會出現塊斷裂的現象。
2.2 LOG BUFFER 說明
2.2.1 Log Buffer 說明
--官網的說明:
The redolog buffer is a circular buffer in the SGA that stores redo entriesdescribing changes made to the database. Redo entries contain theinformation necessary to reconstruct, or redo, changes made to the database byDML or DDL operations. Database recovery applies redo entries to data files toreconstruct lost changes.
Oracle Databaseprocesses copy redo entriesfrom the user memory space to the redo log buffer in the SGA. The redo entriestake up continuous, sequential space in the buffer. The background process logwriter (LGWR) writes the redo log buffer to the active online redo loggroup on disk. Figure14-8 shows this redo buffer activity.
LGWR writes redosequentially to disk while DBWn performs scattered writes of data blocksto disk. Scattered writes tend to be much slower than sequential writes.Because LGWR enable users to avoid waiting for DBWn to complete its slowwrites, the database delivers better performance.
The LOG_BUFFER initializationparameter specifies the amount of memory that Oracle Database uses whenbuffering redo entries. Unlike other SGA components, the redo log buffer andfixed SGA buffer do not divide memory into granules.
--MOS: [ID 147471.1]
The redo logbuffer is a circular buffer in the SGA that holds information about changesmade to the database. This information is stored in redo entries. Redo entriescontain the information necessary to reconstruct, or redo changes made to thedatabase . Redo entries are used for database recovery, if necessary.
Redo entries arecopied by Oracle server processes from the user's memory space to the redo logbuffer in the SGA. The redo entries take up continuous, sequential space in thebuffer. The background process LGWR writes the redo log buffer to the activeonline redo log file (or group of files) on disk.
The initialization parameter LOG_BUFFER determines the size (in bytes) of the redolog buffer. In general, larger values reduce log file I/O, particularly iftransactions are long or numerous. The default setting is four times themaximum data block size for the host operating system prior to 8i and 512k or128k x cpu_count whichever is greater, from 8i onwards.
-- MOS: [ID 147471.1] Redolog Latches
Whena change to a data block needs to be done, it requires to create a redo recordin the redolog buffer executing the following steps:
(1) Ensure that no other processeshas generated a higher SCN
(2) Find for space available towrite the redo record. If there is no space available then the LGWR must writeto disk or issue a log switch
(3) Allocate the space needed inthe redo log buffer
(4) Copy the redo record to the logbuffer and link it to the appropriate structures for recovery purposes.
The database has threeredo latches to handle this process:
(1)Redo Copy latch
The redocopy latch is acquired for the whole duration of the process describedabove. The init.ora LOG_SIMULTANEOUS_COPIES determines the number of redo copylatches. It is only released when a log switch is generated to release freespace and re-acquired once the log switch ends.
(2)Redo allocation latch
The redoallocation latch is acquired to allocate memory space in the log buffer. BeforeOracle9.2, the redo allocation latch is unique and thus serializes the writingof entries to the log buffer cache of the SGA. In Oracle 9.2. EntrepriseEdition, the number of redo allocation latches is determined by init.oraLOG_PARALLELISM. The redo allocation latch allocates space in the logbuffer cache for each transaction entry. If transactions are small, or ifthere is only one CPU on the server, then the redo allocation latch also copiesthe transaction data into the log buffer cache. If a log switch is needed toget free space this latch is released as well with the redo copy latch.
(3)Redo writing latch
This uniquelatch prevent multiple processes posting the LGWR process requesting logswitch simultaneously. A process that needs free space must acquire the latchbefore of deciding whether to post the LGWR to perform a write, execute a logswitch or just wait.
-- MOS: [ID 147471.1]
Instance ParametersRelated with the Redolog Latches
In Oracle7 andOracle 8.0, there are two parameters that modify the behavior of the latchallocation in the redolog buffer: LOG_SIMULTANEOUS_COPIES (This parametercontrols the number of redo copy latches when the system has morethan one CPU), and LOG_SMALL_ENTRY_MAX_SIZE. When LOG_SIMULTANEOUS_COPIESis set to a non-zero value, and the size of the transaction entry is smallerthan the value of the LOG_SMALL_ENTRY_MAX_SIZE parameter then the copy of thetransaction entry into the log buffer cache is performed by the redoallocation latch. If the size of the transaction entry exceedsLOG_SMALL_ENTRY_MAX_SIZE, then the transaction entry is copied into the logbuffer cache by the redo copy latch.
In Oracle8i andOracle9.0, a redo copy latch is always required regardless of the redo size sothe check is no longer performed. The init.ora LOG_SIMULTANEOUS_COPIES becomesobsolete and the number of redo copy latches defaults to twice the number ofcpus. The parameter LOG_SMALL_ENTRY_MAX_SIZE is also obsolete. For furtherdetail on the change of this parameters in Oracle 8i seeNote:94271.1
In Oracle9.2 andhigher, multiple redo allocation latches become possible with init.oraLOG_PARALLELISM. The log buffer is split in multiple LOG_PARALLELISM areas thateach have a size of init.ora LOG_BUFFER. The allocation job of each area isprotected by a specific redo allocation latch. The number of redo copy latchesis still determined by the number of cpus
LOG BUFFER 是SGA中一塊循環使用的內存區域,它一般很小.
在Oracle 10g之前,LOG BUFFER參數的默認設置為Max(512 KB,128 KB * CPU_COUNT),按照默認設置,LOG_BUFFER消耗的內存都不會太高,而由于LGWR對Log Buffer內容的寫出非常頻繁,所以很小的Log Buffer也可以工作得很好,根據經驗,有很多對Log Buffer的指導性設置,比如經常提到的3MB大小,但是在Oracle10g中,Redo Log Buffer默認的已經大大超過了原來的想象。
這和Oracle 9i引入了Granule的概念有關,在動態SGA管理中,Granule是最小的內存分配單元,其大小與SGA及操作系統平臺有關。
在10g中ORACLE會自動調整它的值,他遵循這樣一個原則,'Fixed SGA Size'+ 'Redo Buffers'是granule size 的整數倍(如果是一倍,那么他們的比值可能為0.999...如果是2倍,那么他們的比值可能是1.999...)。
一般的granule value 為4194304 ,也就是4M, 而fixed size 一般為 1.2M,這個值不確定,也不精確,根據不同的平臺有所差異,而默認的log_buffer+fixedsize 的大小為 granulesize 的整數倍,所以默認的情況下你看見的log_buffer大小約為6.67m或者為2.7M。
所以如果我們手動的設置log_buffer的值,那么ORACLE會將它加上fixedsize 然后除以granule ,得到一個值,然后四舍五入,看最接近哪個整數,然后就取最接近的那個值。
SQL> select * from v$version whererownum <2;
BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise EditionRelease 10.2.0.4.0 - Prod
SQL> select * from v$sgainfo where namein ('Fixed SGA Size','Redo Buffers','Granule Size');
NAME BYTES RES
-------------------------------- -------------
Fixed SGA Size 1270508 No
Redo Buffers 2920448 No
Granule Size 4194304 No
SQL> select sum(bytes)/1024/1024 fromv$sgainfo where name in ('Fixed SGA Size','Redo Buffers');
SUM(BYTES)/1024/1024
--------------------
3.9968071
--查看'FixedSGA Size' + 'Redo Buffers' 與 Granule Size的比值:
SQL> select 3.9968071/4 from dual;
3.9968071/4
-----------
.999201775
這里驗證了我們前面的說法:'Fixed SGA Size' + 'Redo Buffers' 是Granule Size 整數倍。
2.2.2 Log Buffer 中的Latch
由于log buffer是一塊“共享”內存,為了避免沖突,它是受到redo allocation latch保護的,每個服務進程需要先獲取到該latch才能分配redobuffer。因此在高并發且數據修改頻繁的oltp系統中,我們通常可以觀察到redoallocation latch的等待。
為了減少redo allocation latch等待,在oracle 9.2中,引入了log buffer的并行機制。其基本原理就是,將log buffer劃分為多個小的buffer,這些小的buffer被成為Shared Strand。每一個strand受到一個單獨redo allocation latch的保護。多個shared strand的出現,使原來序列化的redo buffer分配變成了并行的過程,從而減少了redo allocationlatch等待。
為了進一步降低redo buffer沖突,在10g中引入了新的strand機制——Private strand。Private strand不是從log buffer中劃分的,而是在shared pool中分配的一塊內存空間。
Private strand的引入為Oracle的Redo/Undo機制帶來很大的變化。每一個Private strand受到一個單獨的redo allocation latch保護,每個Private strand作為“私有的”strand只會服務于一個活動事務。獲取到了Private strand的用戶事務不是在PGA中而是在Private strand生成Redo,當flush private strand或者commit時,Privatestrand被批量寫入log文件中。如果新事務申請不到Private strand的redo allocation latch,則會繼續遵循舊的redo buffer機制,申請寫入shared strand中。事務是否使用Private strand,可以由x$ktcxb的字段ktcxbflg的新增的第13位鑒定。
對于使用Private strand的事務,無需先申請Redo Copy Latch,也無需申請Shared Strand的redo allocation latch,而是flush或commit是批量寫入磁盤,因此減少了Redo Copy Latch和redo allocation latch申請/釋放次數、也減少了這些latch的等待,從而降低了CPU的負荷。
2.2.3 Log Buffer 大小問題
一般默認情況下的log_buffer的大小夠用了,查看Log_buffer是否需要調整,可以查看數據庫是否有大量的log buffer space等待事件出現。redo log 最開始是在pga中的uga產生的(數據庫一般是專有模式),oracle會把它拷貝到SGA中的log_buffer中去,如果log_buffer過小,或者lgwr不能夠快速將redo 寫入到log file中,那么就會產生log buffer space等待事件,遇到此類問題,可以增加 log_buffer大小,調整log file 到裸設備,I/0快的磁盤中。
MOS有兩篇相關的文章:
(1)Oracle Calculation of Log_Buffer Size in 10g [ID604351.1]
A big difference can be seen between 10.2.0.3 and 10.2.0.4 when usingthe same system configuration (in terms of the application and its dbobjects and datafiles, ram size, number of CPUs etc). In 10.2.0.3 it was set byOracle to 14M and now in 10.2.0.4 to 15M.
--在10.2.0.3 中Log Buffer 默認值是14M,在10.2.0.4中,默認值是15M。
The LOG_BUFFERsize will be set by default, by Oracle internal algorithm.
In 10G R2,Oracle combines fixed SGA area and redo buffer [log buffer] together.
(2)Tuning the Redolog Buffer Cache and Resolving RedoLatch Contention [ID 147471.1]
相關內容出處鏈接:
http://www.dbtan.com/2009/12/set-redo-log-buffer-size.html
http://www.dbtan.com/2009/12/redo-writes-triggering-condition.html
http://book.51cto.com/art/201001/177245.htm
http://blog.csdn.net/tianlesoftware/article/details/5594080
Privatestrand flush not complete 說明
http://blog.csdn.net/tianlesoftware/article/details/6015400
2.3 LOG BUFFER 和LGWR 的算法
了解LOG BUFFER 和LGWR 的算法,有助于我們分析和解決相關的性能問題,因此我們需要花一點時間來了解LOG BUFFER 相關的基本算法。用一句話來概括,LOG BUFFER是一個循環使用的順序型BUFFER。這句話里包含了兩個含義,一個是LOG BUFFER 是一個順序讀寫的BUFFER,LOG BUFFER 數據的寫入是順序的;第二個含義是LOG BUFFER是一個循環BUFFER,當LOG BUFFER 寫滿后,會回到頭上來繼續寫入REDO LOG 信息。
LOG BUFFER 數據的寫入是由前臺進程完成的,這個寫入操作是并發的,每個前臺進程在生成了REDOLOG 信息后,需要首先在LOGBUFFER 中分配空間,然后將REDOLOG 信息寫入到LOGBUFFER 中去。在LOG BUFFER中分配空間是一個串行的操作,因此Oracle 在設計這方面的算法的時候,把LOG BUFFER 空間分配和將REDO LOG 數據拷貝到LOG BUFFER 中這兩個操作分離了,一旦分配了LOG BUFFER 空間,就可以釋放相關的閂鎖,其他前臺進程就可以繼續分配空間了(這里所說的前臺進程只是一個泛指,是為了表述方便而已,讀者一定要注意,因為后臺進程也會對數據庫進行修改,也需要產生REDO LOG 信息,后臺進程的REDO 操作和前臺進程是大體一致的)。
前臺進程寫入REDO 信息會使LOG BUFFER的尾部指針不停的向前推進,而LGWR這個后臺進程不聽的從LOG BUFFER 的頭部指針處開始查找還未寫入REDO LOG 文件的LOG BUFFER 信息,并將這些信息寫入REDO LOG 文件中,并且將BUFFER 頭部指針不停的向后推進,一旦LOG BUFFER 的頭部指針和尾部指針重合,那么就說嘛了當前的LOG BUFFER 是空的。
而如果前臺進程在LOG BUFFER 中分配空間會使LOG BUFFER 的尾部指針一直向前推進,一旦LOG BUFFER 的尾部指針追上了LOG BUFFER 的頭部指針,那么說明目前LOG BUFFER 中無法分配新的空間給后臺進程了,后臺進程必須要等候LGWR將這些數據寫入REDOLOG 文件,然后向前推進了頭部指針,才可能再次獲得新的可用BUFFER 空間。這個時候,前臺進程會等待LOG FILE SYNC 事件。
為了讓LGWR 盡快將LOG BUFFER 中的數據寫入REDO LOG 文件,以便于騰出更多的空閑空間,Oracle 數據庫設計了LGWR 寫的觸發條件:
1. 用戶提交
2. 有1/3重做日志緩沖區未被寫入磁盤
3. 有大于1M的重做日志緩沖區未被寫入磁盤
4. 每隔3 秒鐘
5. DBWR 需要寫入的數據的SCN大于LGWR記錄的SCN,DBWR 觸發LGWR寫入。
當事務提交時,會產生一個提交的REDO RECORD,這個RECORD 寫入LOG BUFFER 后,前臺進程會觸發LGWR 寫操作,這個時候前臺進程就會等待LOG FILE SYNC 等待,直到LGWR 將相關的數據寫入REDOLOG 文件,這個等待就會結束,前臺進程就會收到提交成功的消息。如果我們的系統中,每秒的事務數量較大,比如幾十個或者幾百個,甚至大型OLTP 系統可能會達到每秒數千個事務。在這種系統中,LGWR由于事務提交而被激發的頻率很高,LOG BUFFER 的信息會被很快的寫入REDO LOG 文件中。
而對于某些系統來說,平均每個事務的大小很大,平均每個事務生成的REDO LOG 數據量也很大,比如1M 甚至更高,平均每秒鐘的事務數很少,比如1-2 個甚至小于一個,那么這種系統中LGWR 由于事務提交而被激發的頻率很低,可能導致REDO LOG 信息在LOG BUFFER 中被大量積壓,oracle 設計的LOG BUFFER 中數據超過1M 的LGWR 激發條件就是為了解決這種情況而設計的,當LOG BUFFER 中的積壓數據很多時,雖然沒有事務提交,也會觸發LGWR 將BUFFER 中的數據寫入REDO LOG 文件。
除此之外,Oracle 還通過了_LOG_IO_SIZE 這個隱含參數來進一步控制LGWR 寫操作,當LOGBUFFER 中的數據超過了這個隱含參數的規定的大小,也會觸發LGWR 被激發。這個參數的缺省值是LOGBUFFER 大小的1/3,這個參數單位是REDO LOG BLOCK。這個參數可以控制當LOG BUFFER 中有多少個數據塊被占用時,就要觸發LGWR 寫操作,從而避免LOG BUFFER 被用盡。
如果一個系統很空閑,很長時間都沒有事務提交,LOG BUFFER 的使用也很少,就可能會導致LOG BUFFER 中的數據長期沒有被寫入REDO LOG 文件,帶來丟失數據的風險,因此Oracle 還設計了一個LGWR 寫的激發控件,設置了一個時間觸發器,每隔的尾部已經追上了LOG BUFFER 的頭部,那么前臺進程就要等待LGWR 進程將頭部的數據寫入REDOLOG 文件,然后釋放LOGBUFFER 空間。這個時候,沒有做提交操作的前臺進程都會等待LOG FILE SYNC 事件。這種情況下,加大LOG BUFFER 就可能可以減少大部分的LOG FILE SYNC 等待了。
加大LOG BUFFER 的大小,可能會帶來另外一個問題,比如LOG BUFFER 從1M 增加到30M(關于LOG BUFFER 是否需要大于3M 的問題,以前我們已經多次討論,因此在這里不再討論了,大家只需要記住一點就可以了,LOG BUFFER 大于3M 浪費空間,對性能影響不大的觀點是錯誤的),那么_LOG_IO_SIZE 自動會從300K 增加到10M,在一個平均每秒事務數較少,并且每個事務的REDO SIZE 較大的系統中,觸發LGWR 寫操作的LOG BUFFER 數據量會達到1M。
一般來說,在一個大型的OLTP 系統里,每次LGWR 寫入REDO LOG 文件的大小在幾K 到幾十K 之間,平均LOG FILE SYNC 的時間在1-10 毫秒之間。如果平均每次寫入的數據量過大,會導致LOG FILE SYNC 的等待時間變長。因此在這種情況下,就可能需要設置_LOG_IO_SIZE 參數,確保LOG FILE SYNC 等待不要過長。
如果每次寫入REDO LOG 文件的數據量也不大,而LOG FILE SYNC 等待時間很吵,比如說超過100 毫秒,那么我們就要分析一下REDOLOG 文件的IO 性能了,如果REDO LOG 文件IO 性能不佳,或者該文件所在的IO 熱點較大,也可能導致LOGFILE SYNC 等待時間偏大,這種情況,我們可以查看后臺進程的LOG FILE PARALLEL WRITE 這個等待事件,這個等待事件一般的等待時間為幾個毫秒,如果這個等待事件的平均等待時間較長,那么說明REDO LOG 文件的IO 性能不佳,需要將REDOLOG 文件放到IO 量較小,性能較快的磁盤上。
在OLTP 系統上,REDO LOG 文件的寫操作主要是小型的,比較頻繁,一般的寫大小在幾K,而每秒鐘產生的寫IO 次數會達到幾十次,數百次甚至上千次。因此REDO LOG文件適合存放于IOPS 較高的轉速較快的磁盤上,IOPS 僅能達到數百次的SATA 盤不適合存放REDO LOG 文件。另外由于REDO LOG 文件的寫入是串行的,因此對于REDO LOG文件所做的底層條帶化處理,對于REDO LOG 寫性能的提升是十分有限的。
三.日志切換和REDO LOG 文件
當前臺進程在LOG BUFFER 中分配空間的時候,實際上已經在REDO LOG 文件中預先分配了空間,如果REDO LOG 文件已經寫滿,無法再分配空間給前臺進程的時候,就需要做一次日志切換,這個時候前臺進程會想LGWR 發出一個日志切換的請求,然后等待log file switch completion 等待事件。
日志切換請求發出后,CKPT 進程會進行一次日志切換CHECKPOINT,而LGWR 開始進行日志切換工作。首先LGWR 進程會通過控制文件中的雙向鏈表,查找到一個可用的REDO LOG 文件,作為新的CURRENT REDO LOG。 查找新的CURRENT REDO LOG 的算法是要求該日志是非ACTIVE 的,并且已經完成了歸檔(如果是歸檔模式),oracle 會優先使用unused 狀態的REDO LOG 組作為CURRENT REDO LOG。
在做日志切換時,首先要將LOG BUFFER 中還沒有寫入REDO LOG 文件的REDO RECORD 寫入當前的REDO LOG 文件,然后將最后一個REDO RECORD 的SCN 作為本日志文件的HIGHSCN 記錄在REDO LOG 文件頭中。這些操作完成后,就可以關閉當前日志了。
完成了上一個步驟,就需要進行第二次控制文件事務,將剛剛關閉的REDO LOG 標識為ACTIVE,將新的當前REDO LOG標識為CURRENT,如果數據庫處于歸檔模式,還要將老的日志組記錄到控制文件歸檔列表記錄中(在V$ARCHIVE 試圖中科看到),并且通知歸檔進程對該日志文件進行歸檔。當所有的歸檔進程都處于忙狀態的時候,并且歸檔進程總數沒有超過log_archive_max_processes 的情況下,LGWR 還會生成一個新的歸檔進程來對老的日志文件進行歸檔。
這些操作完成后,LGWR 打開新的日志組的所有成員,并在文件頭中記錄下初始化信息。
這些完成后,LGWR 修改SGA 中的標志位,允許生成新的REDO LOG 信息。老的日志組目前還被標志位ACTIVE,當DBWR 完成了CHECKPOINT 所要求的寫批量操作后,該日志組的狀態會被標識為inactive。
從上述日志切換的步驟我們可以看出,日志切換還是有很多工作要做的,而且在日志切換開始到結束之間,日志的生成是被完全禁止的,因此在這個期間,對數據庫的修改操作會被全部阻塞。這也是我們經常提到的:“日志切換是一種較為昂貴的操作”。既然日志切換十分昂貴,對系統性能的影響較大,那么我們就應該想辦法減少日志切換的數量,提高日志切換的速度。
減少日志切換的數量我們可以從兩個方面去考慮,一方面是減少日志的產生量,一方面是加大日志文件的大小。
對于減少日志產生量,常規的辦法不外乎使用NOLOGGING 操作,使用BULK 操作、使用DIRECTPATH WRITE 操作等。不過大家要注意在歸檔模式下合非歸檔模式下,這些NOLOGGING 操作的效果是不同的。
有些DBA 擔心加大REDO LOG 文件后會增加數據丟失的機會。的確,REDO LOG 文件越大,一個REDO LOG 文件所包含的REDO RECORD 的數量就越多,一旦整個REDO LOG文件丟失或者損壞,可能丟失的數據量就會增加。
實際上,整個REDO LOG 丟失的可能性極小,最主要的可能性是REDO LOG 文件被誤刪。如果存儲出現故障,導致了REDO LOG 文件損壞,那么受影響的肯定是所有的REDO LOG 文件,而不是某一個REDO LOG 文件,無論REDO LOG 信息是存在一個REDO LOG 文件中還是存在2 個REDO LOG 文件中,其結果是完全一樣的。
剩下一種情況就是最常見的情況了,就是服務器突然宕機,我們可以來分析一下服務器宕機這種情況,REDO LOG 文件的大小不同可能造成的數據丟失是否會不同。
首先我們要了解一下服務器宕機時可能丟失的數據可能是哪些,如果是已經提交的數據,CHECKPOINT已經推進到的部分,是已經被寫入數據文件了,這部分數據是無論如何都不會丟失的,REDO LOG 是用來恢復最后一次CHECKPOINT 到宕機前被寫入REDO LOG 文件的那部分數據。
由于REDO LOG 文件的寫入是順序的,因此無論這部分數據被寫入到一個文件還是多個文件,并不影響這部分數據的恢復。因此我們可以看出,REDO LOG 文件大小和服務器宕機丟失數據的數量是無關的。
通過前面的分析我們應該已經了解到,系統故障時只有當整個REDO LOG 文件損壞時,REDO LOG 文件的大小才可能與丟失的數據量有關。在絕大多數情況下,加大REDO LOG 文件的大小并不會增加數據丟失的機會。因此我們在考慮REDO LOG 文件大小的時候,基本上可以忽略這個數據丟失的多少的問題。
不過在某些情況下,我們在需要加大REDO LOG 文件大小的時候,要適當的考慮,一是存在DATA GUARD 的情況下,為了減少FAILOVER 時的數據丟失量,我們不宜將REDO LOG 文件設置的過大。另外在存在CDC 或者流復制下游捕獲的環境下,也需要考慮REDO LOG 文件大小和捕獲延時的關系問題。
很多DBA 都受過教育,就是REDO LOG 切換的時間應該盡可能的不低于10-20 分鐘,如果日志切換間隔低于這個值,就要考慮加大REDO LOG 文件的大小。事實上,沒有任何鐵律,只要日志切換并沒有對系統的性能和安全產生嚴重的影響.
Redo Log 和Checkpointnot complete
http://blog.csdn.net/tianlesoftware/article/details/4908066
Oracle 不同故障的恢復方案
http://blog.csdn.net/tianlesoftware/archive/2010/12/30/6106178.aspx
Currentonline Redo 和 Undo 損壞的處理方法
http://blog.csdn.net/tianlesoftware/article/details/6261475
posted on 2013-01-08 19:20 周強 閱讀(4900) 評論(0) 編輯 收藏 引用 所屬分類: c/c++