1. 程式人生 > >【internal】redo生成機制

【internal】redo生成機制

redo生成流程

oracle10g之後引入的IMU(in memory undo)機制,這個機制改變了部分redo的生成機制,所以,redo生成流程必須分兩部分介紹:

傳統流程

IMU機制下的流程。

 

先說下如何區分系統是否使用了IMU。

10g以後,預設是啟用了IMU的,但有些條件下IMU被關閉。

這些條件有

1、RAC環境中

2、資料庫級別啟用了supplement log(任何級別)。

3、系統隱含引數_in_memory_undo引數設定成False的情形下。

4、redo檔案過小,小於50M的情形下。

5、(部分不使用IMU)當系統併發很高,當前所有的IMU Latch都被使用,新的IMU Latch請求都失敗,則會話不會等待IMULatch的釋放,而是直接使用傳統流程,繞過IMU。因此IMU層面不會造成等待。

6、(部分不使用IMU)當一個事務很大,產生的redo或回滾資料超過了共享池中IMU區、privateRedo Strand Area中任何一個的大小,則這個事務將不再使用IMU方式,原本寫的IMU區資料和redo資料將全部刷出。這個時間叫做IMUFlashes。每發生一次這種事件,v$sysstat中的IMU Flushes值將加1。

以上的檢查條件略多,所以,基本上通過

   select * from v$sysstat a where a.NAME like '%IMU%'

 檢視IMUcommits行的值,若這個值為0,則基本是沒啟用IMU了。

   再說下IMU下的redo生成流程

l

流程解析:

    1、server程序從共享池的sql中把目標值拿到PGA中。

   2、申請IMULatch和redo allocation Latch。這裡IMU Latch和redo allocation Latch會有多個,對應privateredo area也會被分成多個strands。申請成功後,則分配IMU和private redo區間,分配完釋放兩個Latch。此區間就成程序私有的了,後續進行DML操作可以直接往裡面寫資料。

    3、從PGA中生成資料塊的更改資訊(資料塊的redochange vector)。

   4、從bufferpool中的對應塊裡找到修改前的值,放入到shared pool中的私有IMU區。並將新值寫入到buffer pool中的資料塊。該塊變成髒塊。

   (4.5)SMON會定期醒來,檢查IMU中的資料,生成undo對應的redo資訊寫入私有redo區,並把資料刷入bufferpool中的undo block,該undo塊成為髒塊。

   5、當事務commit。申請logbuffer區的redo allocation Latch(public area)。申請成功後,為該事務在redo buffer中分配一段空間,釋放Latch。

   6、申請redocopy Latch。申請成功後,把IMU中剩餘資料生成redo,刷到undo block.並在copy Latch保護下把私有redo區中的資料拷貝到bufferpool。拷貝完成後釋放redo copy Latch。

   7、LGWR開始把bufferpool中的資料往磁碟寫。

   8、寫完成後commit完成。

傳統方式下的redo生成流程


流程解析:

    1、server程序從共享池的sql中把目標值拿到PGA中。

   1.5 從bufferpool中把old值拿到PGA中。

   1.6 生成undo塊的redochange vector,生成data塊的redo change vector.

   2、申請redoallocation Latch。申請成功後,則在buffer pool裡分配一段空間,釋放redo allocation Latch。

   3、申請redocopy Latch。

   4、申請成功後將undo的CV和data的CV拷貝到logbuffer。

   5、修改bufferpool中的undo block(轉為dirty block)。

   6、修改bufferpool中data block(轉為dirty block)。

    (此時一個update語句即算結束)

   7、若發生commit,將觸發LGWR把logbuffer中內容寫入到log file。

     (commit完成)

redo檔案格式

redo過程事件分析

log buffer space

事件原因:

    申請logbuffer中的空間不得。

log file sync

事件原因:

    使用者commit之後,等待把相關redo資訊從logbuffer刷入log file的過程。

    造成這個事件的原因主要有:

      1、commit過於頻繁

     2、LGWR工作過慢,一般伴隨著logfile parallel write,則表示IO過慢。

log file parallel write

事件原因:

    LGWR在執行從logbuffer刷入log file過程中,開始物理IO的過程。(開始物理IO之前需要進行一些Latch的申請,以及程序間message的傳遞,這些部分加上物理IO就是logfile sync的過程。)

log file switch(checkpoint incomplete) 

事件原因:

    日誌切換時發生完全檢查點,但這個完全檢查點優先順序並不高,不會立即觸發DBWn程序寫入dirtyblock,因此日誌切換主要等待在關閉當前日誌,開啟新日誌的過程(即log file switch completion),但若日誌組切換了一輪,又切換到當前日誌組,可當前日誌中對應的髒塊還沒有寫完,即日誌仍為active狀態,這時session需要等待DBw0把改日誌對應的髒塊全部寫出,把檢查點scn登記到controlfile和data file header這些內容,這個等待過程就是 log file switch(checkpointincomplete) 。

     所以,造成這個事件的原因主要有

     1、日誌產生的太快大,導致切換過於頻繁。

     2、當前日誌組設定的過少,或過小,導致切換過於頻繁。

     3、DBWn程序寫的太慢,導致一輪日誌切換的時間仍然寫不完。

  log fileswitch completion

      事件原因:

          這個過程主要就是關閉當前日誌,開啟新日誌。

 log fileswitch(private strand flush incomplete)  

      事件原因:

 log fileswitch (archiving needed) 

      事件原因:

遺留問題:

    1、dumpshared pool檢視IMU等相關記憶體。

    2、pbsa和pvsa數目初始化值及如何設定

    3、redobuffer大小的初始化值和設定

    4、相關latch的初始化大小和設定,redoallocation latch、redo copy latch、