Oracle Redo Log 機制 小結(轉載)

Oracle 的Redo 機制DB的一個重要機制,理解這個機制對DBA來講也是很是重要,以前的Blog裏也林林散散的寫了一些,前些日子看老白日記裏也有說明,因此結合老白日記裏的內容,對oracle 的整個Redo log 機制從新整理一下。web

 

一.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/6286330oracle

 

這兩種的區別是:app

(1)    Crash Recovery 是在啓動時DB 自動完成,而MediaRecovery 須要DBA 手工的完成。less

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

 

 

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

 

 

 

 

二.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://blog.csdn.net/tianlesoftware/article/details/5594080

 

 

 

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 文件的大小。事實上,沒有任何鐵律,只要日誌切換並無對系統的性能和安全產生嚴重的影響.

相關文章
相關標籤/搜索