
有關延遲塊兒清除、快照過舊、讀一致的總結,希望把這三個知識點串聯一起做個總結,沒有巨細無遺的寫完每個地方,歡迎大家一起討論,如果有前輩指出錯誤的地方更是不勝感激。 Blockcleanout 并不是指把臟塊兒寫入磁盤,只是單純的指把DB buffer中一個塊從 di
有關延遲塊兒清除、快照過舊、讀一致的總結,希望把這三個知識點串聯一起做個總結,沒有巨細無遺的寫完每個地方,歡迎大家一起討論,如果有前輩指出錯誤的地方更是不勝感激。
Blockcleanout 并不是指把臟塊兒寫入磁盤,只是單純的指把DB buffer中一個塊從 dirty 變為 clean,表明這個塊里面的數據是干凈的、最新的,本質上是更新 block header 中的一個標志位——ITL(Interested Transaction List)和block SCN。
什么是delayed block cleanout?
每當事務commit 時,事務修改過的塊兒就會被 cleanout,不過Clean out有2種方式:fast commit cleanout和delayed blockcleanout。
1.fastcommit cleanout 算是真正意義上的 cleanout,當做fast commit cleanout時,Oracle將事務commit 時的系統scn作為commitSCN,馬上更新block上 ITL 、block scn 和 undo segment header的Transaction table的slot(槽)上的 scn,三者是一致的。
2.delayedblock cleanout 是將 cleanout 操作延后了,由于某些原因只是用commit SCN更新了undo segment header 的 Transaction table 上的slot scn,而并未做block上的更新,等待下次使用此block的時候,再用undo segment header 的 Transaction table 上的slot scn(與之前事務的commit SCN相同)去更新 block scn 和 ITL。(當下一次操作如SELECT,UPDATE,INSERT或DELETE訪問到這些塊時需要在讀入后完成塊清除)
為什么要執行delayed block cleanout呢?
這是出于性能考慮的,我們首先來看哪些塊會做delayed block cleanout
前提:Oracle有一個modifiedblock list 結構(checkpoint queue機制?),用來記錄每個transaction更改過的block,每個transaction可以在這個list上面記錄大約10%buffercache這多的modified block。
事務commit 時:
更改過的block低于10%,則oracle可以根據modified block list定位到那些塊并做fast commit cleanout。
更改過的block超過10%,則超出部分就做delayed block cleanout。
未commit前,由于事務耗時太長已經被寫至磁盤的塊做delayed block cleanout。
這里就可以看出,不立即cleanout 的原因有二,但本質都是不能立刻在DB buffer中找到對應的塊兒,前者是超出10%,沒有在list中記錄,后者是已經寫入磁盤,如果再重新讀回DB buffer再修改,IO太多,都影響性能。
和快照過舊是什么關系?
前提:別的會話用過這個塊兒(clean),或者正在占用這個塊兒(dirty),都會在塊兒上記錄ITL(itl、xid、flag、uda、scn\fsc)。
1.當發出一條select語句時,ORACLE會記錄下這個時刻SCN,然后在buffer cache中查找需要的BLOCK,或者從磁盤上讀。
2.首先要查看最近一個修改這個塊的事務的flag,如果需要cleanout 就馬上執行。如果執行成功或者不需要執行就接著比較ITLSCN和select SCN,如果ITL SCN > select SCN,證明塊兒的版本是比要select的新,要執行讀一致找舊版本。
3.ORACLE就會根據ITL中的uba找到UNDO信息獲得該block的前鏡像,然后在buffercache 中構造出CR塊,此時ORALCE也會檢查構造出來的CR塊兒中ITL記錄的SCN,如果SCN還大于select時刻的SCN,那么一直重復構造前鏡像,直到找到需要的塊兒,這樣ORACLE就實現了多版本。但如果在構造前鏡像的過程中所需的UNDO信息被覆蓋了,就會報快照過舊的錯誤。所以簡單來說,是利用遞推方式去找到和自己select同一SCN的那個塊兒的版本,如果找不到就是快照過舊。
而對于延遲清除的塊兒,盡管對應的事務已經commit,但自己本身還是dirty狀態。之前commit的時候只是更新undo segment header的Transaction table的slot(槽)上的 scn,而塊兒自己的itl 和 block scn卻沒有更新。當再次訪問到這個塊兒的時候,肯定要完成剩余的工作,即上面第二步說的馬上cleanout——更新這個塊兒的itl scn 和 blockscn。之前說過,如果clean執行成功就接著比較ITL SCN和selectSCN來決定是否需要要執行讀一致。但如果因為undo被覆蓋,就獲得不了commit SCN,連cleanout也不能執行,也就比較不了大小了。報錯還是快照過舊。
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com