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(回滾)。


更多內容參考:

還原真實的cache recovery

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的修改不能被寫入數據文件。


相關鏈接:

RedoLogCheckpoint 和 SCN關係

http://blog.csdn.net/tianlesoftware/article/details/5251916


Oraclecheckpoint 說明

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.

0_13315537010Ur8.gif


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


Oracle 內存 架構 詳解

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



再次聲明:這篇文章是Dave 根據其他資料整理而成。





-------------------------------------------------------------------------------------------------------

版權所有,文章允許轉載,但必須以鏈接方式註明源地址,否則追究法律責任!

Email:   [email protected]

Skype: tianlesoftware

Blog:     http://www.tianlesoftware.com

Weibo: http://weibo.com/tianlesoftware

Twitter: http://twitter.com/tianlesoftware

Facebook:http://www.facebook.com/tianlesoftware


-------加羣需要在備註說明Oracle表空間和數據文件的關係,否則拒絕申請----

DBA1 羣:62697716(滿);   DBA2 羣:62697977(滿)  DBA3 羣:62697850(滿)  

DBA 超級羣:63306533(滿);  DBA4 羣:83829929   DBA5羣: 142216823

DBA6 羣:158654907    DBA7 羣:172855474   DBA總羣:104207940

轉自DAVE http://blog.csdn.net/tianlesoftware/article/details/7346212


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章