sql執行過程 延遲塊清除

2021-06-28 03:49:30 字數 1592 閱讀 8124

delete

1.oracle讀block到buffer cache(如果該block在buffer中不存在)

2.在相應回滾段段頭的事務表中建立乙個undo條目(undo條目指向的一塊空間)

3.將要變化的記錄(不是整個資料塊)的前映象放到undo中。如果這時有別的會話需要讀取這條記錄,oracle先將這條記錄所在的資料塊複製乙份,然後用undo中那條記錄的前映像"舊化"這個資料塊,這樣一致讀的資料塊就構建完成了。

4.在redo log buffer中記錄此次操作的產生redo 資料和undo資料

5.在buffer cache中的相應資料塊上修改記錄,並且標記相應的資料塊為dirty

提交(commit)

1.oracle產生乙個scn

2.在回滾段事務表中標記該事務狀態為commited

3.lgwr flush log buffer到日誌檔案

3.如果此時資料塊仍然在buffer cache中,那麼scn將被記錄到block header上,這被稱為快速提交(fast commit)

4.如果記憶體不夠,dirty block已經被寫回到磁碟,那麼下乙個訪問這個block的程序,會定位到資料塊上要獲取的行,從行頭找到資料塊頭中itl事務表中

對應的事務條目,從該事務條目中判斷該事務有沒有提交(因為在提交前就寫入磁碟了,來不及標記提交標記),如果沒有提交,將會根據從該事務條目中找到在回滾段中對應的位址,根據位址進入

回滾段中獲取該事務的狀態。如果事務被提交,則將提交scn並寫回到block header中的itl事務表中的對應的事務條目中。這被稱為延遲塊清除。

如果回滾段中的事務條目由於時間太久已經被覆蓋了,那oracle會從當前回滾段中找到乙個最小的commit  scn更新這個延遲塊清除的塊的塊頭中的itl,

從而完成塊清除。(這雖然不準確,但是是安全的,對於資料訪問也不構成影響。所以叫 upper bound ,猜測的乙個scn的上限。)

如果當前的查詢時的scn比這個最小的commit   scn還小,說明事務的提交scn可能也大於當前查詢的scn。則產生01555錯誤,由於報錯後寫回了乙個當前回滾段中最小的提交scn,那麼下次就不會再觸發

01555這個錯誤了;如果當前的查詢時的scn比回滾段中最小的commit scn大,那麼當前查詢的scn肯定大於已經被覆蓋的事務的scn,則可以直接用這個延遲清除的塊構建一致讀

資料塊寫回磁碟——回滾段中記錄還在——事務未提交:重新讀入資料塊,構建一致讀,正常讀取

資料塊寫回磁碟——回滾段中記錄還在——事務已提交:重新讀入資料塊,構建一致讀,正常讀取

資料塊寫回磁碟——回滾段中記錄被覆蓋:延遲塊清除(如上所訴)

資料塊在記憶體——回滾段中記錄還在:正常讀取

資料塊在記憶體——回滾段中記錄被覆蓋:ora-01555錯誤,回滾段太小

一致讀時,oracle會一直找到(或者構建出)比當前查詢scn還小的且已經提交的資料版本。如果找不到,就是ora-01555錯誤。

那假如事務槽被覆蓋了怎麼實現一致讀呢?

如果事務槽被覆蓋了也沒事,因為當前事務槽中

的uba 可以找到回滾段位址

,回滾段中除了記錄資料的 before image 外

還記錄了被它覆蓋的事務槽的記錄。可以形成乙個鍊錶

直接路徑讀取對於延遲塊清除的影響

在oracle 11g版本中序列的全表掃瞄可能使用直接路徑讀取 direct path read 的方式取代之前版本中一直使用的db file scattered read,顯然direct path read具備更多的優勢 1.減少了對栓的使用,避免可能的栓爭用 2.物理io的大小不再取決於buf...

sql執行過程

程式中寫的一條sql傳送到伺服器端 查詢此條sql是否存在執行計畫 如果存在則直接呼叫已經編譯好的執行計畫 否則進入下一步。如果sql計畫快取中沒有對應的執行計畫,則進行語法校驗 檢視是否存在語法錯誤 如果語法沒有錯誤則進行語義校驗,例如,表名,列名,儲存過程等等資料庫物件是否真正存在 如果語義沒有...

SQL執行過程

mysql server pluggable storage engines 1 客戶端 服務端通訊協議 查詢快取,如果有資料返回,否則繼續 複製 2 解析器根據解析樹解析 預處理器檢測正常繼續,否則報錯 比如要查詢的字段不存在 複製 3 查詢優化器 explain查詢執行計畫 好比以前我們除錯介面...