簡單點說,在oracle的block上都有活動事務的標誌的,如果一個事務commit後,由於某些block在commit之前已經寫回datafile,或者事務影響到的block數過多,則commit的時候只會清理undo segment header中的事務表資訊,data block上的事務標誌不會清除,在否則代價過高。那麼在一些讀取這些block時,需要將這些事務標誌進行清除,就是延遲塊清除
塊清除即清除資料區塊上與“鎖定”有關的資訊。Oracle的鎖機制是一種輕量級的鎖定機制,不是通過構建鎖列表來進行資料的鎖定管理,而是直接將鎖作為資料的屬性,儲存在資料區塊首部。因此,每次訪問資料時都要去看資料區塊頭部的鎖,如果資料已經提交,則可能需要清理這個塊,換句話說,要將這些事務資訊刪除。因此這個動作就會產生redo。
Cleanout有2種,一種是fast commit cleanout(提交清除),另一種是delayed block cleanout(延遲清除).
提交清楚是如何工作的?Oracle會記錄已修改的塊列表,這些列表可以有20個塊,Oracle根據需要分配多個這樣的列表,但是如果這些修改的塊加起來超過buffer_cache的10%,oracle就停止分配這樣的列表,因此當提交時就只會清理最多10%buffer_cache的資料區塊,其餘的部分就延遲清除,這樣也是為了提高commit的效率。
還有一種情況,就是當事務還未commit時,修改的資料區塊已經寫入硬碟,當發生commit時oracle並不會把block重新讀入做cleanout,而是把cleanout留到下一次對此塊的訪問是完成。
Cleanout有2種,一種是fast commit cleanout,
另一種是delayed block cleanout.Oracle的每個事務(transaction)修改不超過10%buffer cache的資料區塊時,oracle做的是fast commit cleanout。如果一個事務(transaction)修改的塊超過10% buffer cache,那麼超過的塊就執行delayed block cleanout,還有一種情況,就是當事務還未commit時,修改的資料區塊已經寫入硬碟,當發生commit時oracle並不會把block重新讀入做cleanout,而是把cleanout留到下一次對此塊的訪問是完成。
當我們update 資料之後,並且沒有commit,此時我們flush buffer cache,將修改的資料區塊,flush 到硬碟,那麼此時發生的就是delay block cleanout
正常情況下,會去修改block裡的相關SCN。 但是實際上此時Oracle 並沒有回去修改這些block,因為再次調用成本太大。 Oracle只更新了undo segment header slot。 當下次再次訪問這個block時,在根據undo segment 來更新block scn 和 itl 上的scn。 如果此時對應的undo segment 已經不存在,就會出發ORA-01555,快照過舊的錯誤。
做了delayed block cleanout之後,itl 變成了SCN。 此時lck,lb標誌為都被清零,scn也是從undo segment header transactiontable slot裡面得到。如果undosegment header 上的slot被覆蓋了,那麼會把undo segment 上的control scn拿來當作upper bound scn
當delayed block cleanout 發生時,依賴與undo segment來保證,如果undo segment 被刪除了,那麼會Oracle 會使用system 資料表空間下的undo$ 基表來保證delayed block cleanout。
一般來說,select 是不會產生redo的。 但如果發生了delayed block cleanout,那麼就會產生redo。 當然這隻是一種情況,開啟審計等,也會造成select 產生redo。