ORACLE的工作機制-3

junsansi發表於2007-08-09

ORACLE的工作機制-3 (by xyf_tck)

只有當SQL語句影響的所有行所在的最後一個塊被讀入DB BUFFER並且重做資訊被寫入REDO LOG BUFFER(僅是指重做日誌緩衝,而非重做日誌檔案)之後,使用者才可以發出COMMIT,COMMIT觸發LGRW,但並不強制立即DBWN來釋放所有相應的DB BUFFER塊上的鎖,也就是說有可能出現已COMMIT,但在隨後的一段時間內DBWN還在寫這條語句涉及的資料塊的情形,表頭部的行鎖,並不是在COMMIT一發出就馬上釋放,實際上要等到相應的DBWN程式結束才會釋放。一個使用者請求鎖定另一個使用者已COMMIT的資源不成功的機會是存在的。COMMIT發出後會將回滾段中的"前映像"標識為已提交.DML語句會產生一個SCN號,DBWN觸發時寫入到資料塊的頭部,COMMIT時也會產生一個SCN號,也會被寫入資料塊的頭部。在資料塊的頭部只儲存一個最新的SCN號,COMMIT之後這個事務插槽可以被另外一個事務使用。如果使用者ROOLBACK,則伺服器程式會根據資料檔案塊和DB BUFFER中塊的頭部的事務列表和SCN以及回滾段地址重構出相應的修改前的副本,並且用這些原值來還原當前資料檔案中已修改但未提交的改變。如果有多個"前映像",伺服器程式會在一個"前映像"的頭部找到"前前映像"的回滾段地址,一直重構出同一事務下的最早的一個"前映像"為止。一旦發出了COMMIT,使用者就不能ROLLBACK,這使得COMMIT後DBWN程式還沒有全部完成的後續動作得到了保障。下面我們要提到檢查點的作用,ckpt的觸發,有以下幾種情況: 1.當發生日誌組切換的時候 2.當滿足log_checkpoint_timeout、log_checkpoint_interval、fast_start_io_target、fast_start_mttr_target引數設定的時候 3.當執行alter system switchlogfile的時候 4.當執行alter systemckeckpoint的時候 5.當執行altertablespacetbs_namebegin backup[end backup]的時候 6.當執行altertablespace[datafile] offline的時候 7.系統正常關閉時只有在4.7兩種情況下發生完全檢查點。發生完全檢查點時,首先系統記錄檢查點對應的Checkpoint SCN,並記錄下該時刻修改的DB BUFFER對應的日誌檔案的最新的重做位元組地址(Redo Byte Address (RBA)),然後DBWN程式將這個重做位元組地址(RBA)之前已發生的DB BUFFER中的髒緩衝寫入資料檔案(之所以要以重做位元組地址(RBA)為標誌是因為在檢查點發生到檢查點完成之間的時間內,系統還在一直不斷的產生修改,這些修改所產生的DB BUFFER髒緩衝,以及日誌條目將不會影響這次檢查點最後確認的一致性結果,也就是最後確認這個Checkpoint SCN之前的系統是一致的)。最後把Checkpoint SCN和RBA更新至控制檔案,Checkpoint SCN更新至每個資料檔案頭部,表明當前資料庫是一致的。日誌切換並不導致一個完全檢點的發生,比如有三個日誌檔案組,當發生日誌切換時發生檢查點,而發生日誌切換一般是因為當前的LGWR正在寫重做日誌,也就是LGWR當剛寫滿2號日誌就立即觸發檢查點,於是系統開始核對3號日誌中記錄的REDO專案所對應的資料是否已經從DB BUFFER中寫入資料檔案(不管事務是否已提交),如果沒有寫入,檢查點就觸發DBWN程式將這些緩衝塊寫入資料檔案,顯然LGWR因此而發生等待,除此以外,檢查點還讓DBWN程式將在2號日誌中對應修改的DB BUFFER塊寫入資料檔案,然後繼續LGWR程式,直到LGWR程式將LGWR觸發之前存在於REDO LOG BUFFER中的所有緩衝(包含未提交的重做資訊)寫入重做日誌檔案,檢查點再更新資料檔案,控制檔案頭部SCN。其實LGWR等待的並不是CKPT的完成,而是等待CKPT觸發的DBWN程式的完成。可以想像斷電時可能既有未COMMIT的事務,也可能同時存在已COMMIT但DBWN未完成的情況,如果斷電時有一個已COMMIT但DBWN動作沒有完成的情況存在,因為已經COMMIT,COMMIT會觸發LGWR程式,所以不管DBWN動作是否已完成,該語句將要影響的行及其產生的結果一定已經記錄在重做日誌檔案中了,則例項重啟後,SMON程式從控制檔案中記錄的上一次重做位元組地址(RBA)開始,按照重做日誌檔案中的條目對資料檔案和回滾段重新做一遍即前滾,注意這些條目的操作在斷電之前有的已經被DBWN寫入了資料檔案,有的還沒有來得及寫,不管有沒有寫進資料檔案,前滾時都會再重新寫一次(9I之前是這樣的),9I之後,由於也在日誌中記錄了DBWN改寫的塊資訊,系統會過濾掉已寫入的條目而只重做那些未寫入的條目。對於一個未提交事務,分幾種情況來描述:1)LGWR與DBWN一致的情況即一個語句執行完成後很長時間也沒有COMMIT,這種情況一般不存在DBWN來不及完成的情況。只是沒有COMMIT而已。那麼SMON將在前滾完成後,利用回滾段重構出具有最小SCN的前映像,並把它的值寫回原位。2)事務執行中斷電,即可能存在LGWR與DBWN不同步的情況(因為DBWN之前會觸發LGWR,所以DBWN對資料檔案的修改一定會被先記錄在重做日誌檔案中。因此只可能存在已寫入重做日誌而未來得及寫入資料檔案的情況存在。而不可能存在已寫入資料檔案卻沒有寫入日誌檔案的情況。),這種情況下SMON也會先前滾一點(即把資料檔案與相應的日誌檔案先同步再回滾,之所以說前滾一點,是指僅LGWR與DBWN之間進度的差距,而不是把這條語句進行到底再回滾,因為日誌檔案中記錄的是執行語句操作的一個個塊的修改資訊,而不只是記錄一條執行語句的字面內容),然後利用回滾段重構出具有最小SCN的前映像,並把它的值寫回原位。由此可見,例項失敗後用於恢復的時間由兩個檢查點之間的間隔大小來決定,我們可以通個四個引數設定檢查點執行的頻率,LOG_CHECKPOINT_IMTERVAL決定了兩個檢查點之間寫入重做日誌檔案的系統物理塊的大小,LOG_CHECKPOINT_TIMEOUT決定了兩個檢查點之間的時間長度,FAST_START_IO_TARGET決定了用於恢復時需要處理的塊的大小,FAST_START_MTTR_TARGET直接決定了用於恢復的時間的長短。檢查點的作用就是不斷的確認LGWR與DBWN之間的同步情況,以便例項失敗後從上一個檢查點開始恢復,問題是兩個檢查點之間LGWR與DBWN大部分的操作是同步的,只是一小部分沒有同步,這種傳統的檢查點使例項恢復做了比較多的無用功,因此,ORACLE引入了增量檢查點,增量檢查點會在上一次傳統檢查點發生後到下一次傳統檢查點發生之前,不斷的更新記錄在控制檔案中重做位元組地址(RBA)(CKPT程式每三秒更新一次,見下面DBWN講述),這樣例項失敗後將直接從控制檔案中記錄的最後更新的重做位元組地址(RBA)開始進行前滾和回滾,這就省略掉了恢復時大部份的重做日誌的重做(即使在9I以後的版本里也省略掉了大部分的過濾重做日誌條目的時間)。(對以上描述做一個簡單的比喻:比如一個貿易公司下設經營部、貨運部、監督部,經營部負責貿易合同的簽訂與記錄,貨運部負責按合同號的順序把貨物送達,監督部負責定期檢查確認經營部簽訂的合同與貨運部貨物送達情況之間的同步情況,監督部每月檢查一次,每次檢查時,先確認當時正在裝車的貨物的合同號,並要求貨運部把在這個合同號之前的所有還存在臨時倉庫中的未送貨物全部送達。等貨運部完成監督部下達的任務後,監督部在檢查本上記錄下本次開始檢查時那票正在裝車的貨物的合同號,本次檢查完成。如果這個公司發生了一次人事大換血,公司重新開業後,監督部就會從檢查本上記錄的合同號開始,檢查在這之後所有發生的合同及貨物送達情況,要求貨運部把所有客戶確認的但還未送達的貨物送達。把所有客戶未確認的貨物收回。監督部發現這次重新開業後的工作量實在是太大了,幾乎核對了整整一個月的幾萬單合同(好在不是半年檢查一次^_^),為了防止今後出現這種情況,監督部增加了一項工作內容,每三天派人去記錄一下貨運部正在裝車的那票貨的合同號,今後如果發生類似情況,監督部就從最後一次記錄的合同號開始核對,這樣工作量就小多了。)


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/7607759/viewspace-22274/,如需轉載,請註明出處,否則將追究法律責任。

相關文章