1. 程式人生 > >Oracle Redo Log 機制 小結

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

這兩種的具體說明,參考:

這兩種的區別是:

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

更多內容參考:

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]

相關內容出處連結:

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

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

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

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

QQ:492913789

Email:[email protected]

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