oracle 9i下ORA-01555錯誤的解決方法

sky_dizzy001發表於2014-02-11
導致ora-01555的原因

1、一致性讀
當Oracle更新資料塊(Data Block Oracle中最小的儲存單位)時,會在兩個地方記錄下這一更新動作。一個是重做段(Redo Segment),是用於資料庫恢復(Recover)用的。一個是回滾段(UNDO Segment),而回滾段是用於事務回滾(Rollback)的(我們只關心回滾段了)。並在資料塊頭部標示出來是否有修改資料。一個語句在讀取資料快時,如果發現這個資料塊是在它讀取的過程中被修改的(即開始執行讀操作時並沒有被修改),就不直接從資料塊上讀取資料,而是從相應的回滾段條目中讀取資料。這就保證了最終結果應該是讀操作開始時的那一時刻的快照(snapshot),而不會受到讀期間其他事務的影響。這就是Oracle的一致性讀,也可以叫做多版本(Multi-Versioning)。

2、延遲塊清除
另外一個可能產生1555錯誤的概念——延遲塊清除(Delayed Block Cleanout)。但個人認為,如果不從字面意思上翻譯,應該把它叫做延遲鎖清除更加讓人容易理解一些。
我們知道,當Oracle更新資料塊時,會在回滾段(UNDO Segment)記錄下這一更新動作。並且產生一個Cleanout SCN,在回滾段中,會產生對應的Transaction ID以及相應的資料記錄映象。並在對應的資料記錄上,產生鎖標誌。在事務提交(commit)前,會在資料塊的頭部記錄下這個Cleanout SCN(Csc)號、Undo Block Address(Uba)和Transaction ID(Xid);並且在在對應Interested Transaction List(Itl)中設定鎖標誌,記錄這個事務在這資料塊中產生的鎖的數目;同時在對應修改的資料記錄上打上行級鎖標誌,並對映到對應的Itl去。當提交時,並不會一一清除掉所有鎖標誌,而是給對應的Itl打上相應標誌,告訴後面訪問該資料塊的事務,相應的事務已經提交。這就叫做快速提交(Fast Commit)。而後面訪問該資料塊的的事務就先檢查鎖標誌和對應的事務狀態,如果發現前面的事務沒有提交,並且要訪問的資料記錄被鎖住了,就被阻塞;否則就清除相應的鎖標誌,並提交自己的鎖標誌,再重複以上動作。這就是延遲塊清除。
而如果前面的事務在提交之前buffer cache中的髒資料已經被DBwn程式寫回,那麼Itl中的事務標誌就不會被更新,並且資料塊的Itl列表也不會記錄下事務的Commit SCN。後面的事務或查詢語句訪問該資料塊時,為了檢測是否需要進行一致性讀(如果資料塊的Itl中記錄的提交事務的Commit SCN大於當前訪問該資料塊的SCN,則需要進行一致性讀),就需要透過Undo Block Address和Transaction ID到回滾段的事務資訊表中去檢查前面事務的狀態和它的Commit SCN,確定是否做一致性讀,最後將前面事務在該資料塊上的標誌做一次Cleanout。

解決ora-01555錯誤的方法
 
1、擴大undo表空間
因為回滾段是迴圈使用的,如果回滾段足夠大,那麼那些被提交的資料資訊就能儲存足夠長的時間是那些大事務完成一致性讀取。
 
2、增加undo_retention時間
在undo_retention規定的時間內,任何其他事務都不能覆蓋這些資料。
 
3、最佳化相關查詢語句,減少一致性讀。
減少查詢語句的一致性讀,就降低讀取不到回滾段資料的風險。這一點非常重要!
 
4、減少不必要的事務提交
提交的事務越少,產生的回滾段資訊就越少。
 
5、使用遊標時儘量使用顯式遊標,並且只在需要的時候開啟遊標,同時將所有可以在遊標外做的操作從遊標迴圈中拿出。當遊標開啟時,查詢就開始了,直到遊標關閉。減少遊標的開啟時間,就減少了1555錯誤發生的機率。

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

相關文章