oracle工作機制(2)

jss001發表於2009-03-06

下面是幾個關於回滾段和死鎖的事例:

有表:Test (id number(10)) 有記錄1000000條

一,大SELECT,小UPDATE
A會話----Select * from test;----設scn=101----執行時間09:10:11
B會話-----Update test set id=9999999 where id=1000000----設scn=102-----執行時間09:10:12

我 們會發現B會話會在A會話前完成,A會話中顯示的ID=100000是從回滾段中讀取的,因為A會話在讀到ID=1000000所在的BLOCK時發現 BLOCK上有事務資訊,因此要從回滾段中讀,如果UPDATE在SELECT讀到此BLOCK之前已經COMMIT,則SELECT 讀到此BLOCK時發現其BLOCK上沒有事務資訊,但是會發現其BLICK的SCN比SELECT自己的SCN大,因此也會從回滾段中讀取。因此是否從 回滾段讀一是看是否有事務資訊二是比較SCN大小。如果B會話在A會話結束前連續多次對同一條記錄UPDATE並COMMIT,那麼在回滾段中將記錄多個 “前映像”,而每個“前映像”中不但包括了原BLOCK的資料和SCN也記錄了“前前映像”的回滾段地址,因此A會話在查詢到被UPDATE過的 BLOCK時,會根據BLOCK記錄的回滾段的地址,找到回滾段中的“前映像”,發現這個“前映像”的SCN也比自己的大,因此將根據這個“前映像”中記 錄的“前前映像”的回滾段地址,在回滾段中找到“前前映像”,再與這個“前前映像”比較SCN,如果比自己小就讀取,如果還比自己大,則重複以上步驟,直 到找到比自己SCN小的“前…前映像”為止,如果找不到,就會報ORA-01555快照太舊這個錯誤。

二、大UPDATE,小SELECT

A會話----Update test set id=1;----設scn=101----執行時間09:10:11
B會話-----select * from test where id=1000000----設scn=102-----執行時間09:10:12

我 們會發現B會話會在A會話前完成,B會話中顯示的ID=1000000是從BLOCK中直接讀取的,因為B會話在讀到ID=1000000所在的 BLOCK時,A會話還沒有來得及對其鎖定,因此B會話既不會發現BLOCK上有事務資訊,也不會發現BLOCK上的SCN比SELECT的大,因此會從 BLOCK中直接讀取,如果SELECT在UPDATE鎖定此BLOCK後才發出,B會話讀到此BLOCK時發現其BLOCK上有事務資訊,因此會從回滾 段中讀取。

三、大UPDATE,小UPDATE

A會話----Update test set id=1;----設scn=101----執行時間09:10:11
B會話1-----Update test set id=999999 where id=1000000----設scn=102-----執行時間09:10:12
B會話2----- select * from test where id=2----設scn=103-----執行時間09:10:14
B會話3----- update test set id=3 where id=2----設scn=104-----執行時間09:10:15

我 們會發現B會話1會完成,A會話將一直等待,因為B會話1會先於A會話鎖定ID=1000000所在的BLOCK,並改寫頭部的事務資訊,A會話在試圖鎖 定此BLOCK時,發現其上有事務資訊,將會一直等待B會話1事務結束後再行鎖定, B會話2查詢到的ID=2是從回滾段中讀取的而不是從BLOCK中直接讀出來的。因為A會話已將ID=2的BLOCK鎖定,並寫入了回滾段,從B會話3可 以證明這一點,B會話3發出後,B會話3會收到死鎖的資訊,死鎖的原因是A會話在等待B會話對ID=1000000所在的BLOCK解鎖,現在B會話又在 等待A會話對ID=2所在的BLOCK解鎖,因此形成死鎖,因此證明ID=2所在的BLOCK已被A會話鎖定,然後A會話也會收到死鎖的資訊

[@more@]

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

相關文章