ORA-01555 緣由與解決: sql
前面提到了ORA-01555錯誤,那麼如今來看一下ORA-01555錯誤是怎樣產生的。因爲回滾段是循環使用的,當事務提交之後,該事務佔用的回滾段事務會被標記爲非活動,回滾段空間能夠被覆蓋重用。那麼一個問題就出現了,若是一個查詢須要使用被覆蓋的回滾段構造前鏡像實現一致性讀,那麼此時就會出現Oracle著名的ORA-01555錯誤。 數據庫
ORA-01555錯誤的另一個緣由是由於延遲塊清除(Delayed Block Cleanout)。當一個查詢觸發延遲塊清除時,Oracle須要去查詢回滾段得到該事務的提交SCN,若是事務的前鏡像信息已經被覆蓋,而且查詢SCN也小於回滾段中記錄的最小提交SCN,那麼Oracle將無從判斷查詢SCN和事務提交SCN的大小,此時出現延遲塊清除致使的ORA-01555錯誤。 事件
另一種致使ORA-01555錯誤的狀況出如今使用sqlldr直接方式加載(direct=true)數據時。當經過sqlldr direct=true 方式加載數據時,因爲不產生重作和回滾信息,Oracle直接指定Cached Commit SCN 給加載數據,在訪問這些數據時,有時會產生ORA-01555錯誤。 事務
看下圖的描述:假定在時間T用戶A發出一條更新語句,更新SCOTT用戶的SAL;用戶B在Ty時間發出查詢語句,查詢SCOTT用戶的SAL;用戶A的更新在Tx時間提交,提交可能爲快速提交塊清除,也多是延遲塊清除;用戶B的查詢在Tz時間輸出。 文檔
來看一下數據庫在不一樣狀況下的內部處理: it
·若是 Ty < T < Tz < Tx ,那麼查詢須要構造一致性讀,因爲事務還沒有提交,能夠經過回滾段構造前鏡像,完成一致性讀取。
·若是 Ty < T < Tx < Tz ,因爲Ty查詢時間小於T事務更新時間,那麼數據庫須要構造一致性讀取,而Tz查詢完成時間大於Tx提交時間,那麼前鏡像就有可能被覆蓋,不可獲取。 io若是Tx的提交方式爲Fast Block Cleanout,那麼回滾段信息不可用時就會出現一致性讀ORA-01555錯誤。 event
若是Tx的提交方式爲Delayed Block Cleanout,那麼回滾段信息不可用時Oracle將沒法判斷Ty和Tx的時間前後關係。若是 Ty > Tx ,那麼Oracle能夠正常進行塊清除,並將塊清除後的數據返回給用戶B;若是 Ty < T ,那麼Oracle須要繼續構造一致性讀返回給用戶B;Oracle沒法判斷這兩種狀況,就會出現延遲塊清除ORA-01555錯誤。 ast
ORA-01555的直觀解釋是「snapshot too old」,也就是快照太舊,其根本含義就是查詢須要的前鏡像過於「久遠」,已經沒法找到了。能夠想象,若是一個歷時數個小時或十幾個小時的查詢,若是最後遭遇ORA-01555錯誤而失敗,會是多麼使人沮喪的一件事。一直以來,ORA-01555都是ORACLE最爲頭痛的問題之一。 file
在Oracle 9i的文檔中這樣描述ORA-01555錯誤:
01555, 00000, "snapshot too old: rollback segment number %s with name \"%s\" too small"
// *Cause: rollback records needed by a reader for consistent read are
// overwritten by other writers
// *Action: If in Automatic Undo Management mode, increase undo_retention
// setting. Otherwise, use larger rollback segments
能夠看到,在Oracle 9i自動管理UNDO表空間模式下,UNDO_RETENTION參數的引入正是爲了減小ORA-01555錯誤的出現。這個參數設置當事務提交以後(回滾段變得非活躍),回滾段中的前鏡像數據在被覆蓋前保留的時間,該參數以秒爲單位,9iR1初始值爲900秒,在Oracle 9iR2增長爲10800秒。
顯然該參數設置的越高就越能減小ORA-01555錯誤的出現,可是保留時間和存儲空間是緊密相關的,若是UNDO表空間的存儲空間有限,那麼Oracle就會選擇回收已提交事務佔用的空間,置UNDO_RETENTION參數於不顧。
在Oracle 9i的AUM模式下,UNDO_RETENTION其實是一個非擔保(NO Guaranteed)限制。也就是說,若是有其餘事務須要回滾空間,而空間出現不足時,這些信息仍然會被覆蓋;從Oracle 10g開始,Oracle對於UNDO增長了Guarantee控制,也就是說,能夠指定UNDO表空間必須知足UNDO_RETENTION的限制。當UNDO表空間設置爲Guarantee,那麼提交事務的回滾空間必須被保留足夠的時間,若是UNDO表空間的空間不足,那麼新的事務會因空間不足而失敗,而不是選擇以前的覆蓋。
從各個不一樣版本回滾段的管理變遷,咱們能夠看出Oracle一直在進步。
Oracle提供了一個內部事件(10203事件)能夠用來跟蹤數據庫的塊清除操做,10203事件能夠經過如下命令設置,設置後須要從新啓動數據庫該參數方能生效:
alter system set event="10203 trace name context forever" scope=spfile;
須要注意的是,可能存在另一種狀況,就是當執行延遲塊清除時,回滾段或原回滾表空間已經被刪除,此時Oracle仍然能夠經過字典表UNDO$來得到SCN信息,執行塊清除。
關於Oracle的提交處理及塊清除機制是一個極其複雜的過程,本文對這部份內容進行了適當簡化說明,旨在使你們可以對Oracle的回滾機制、塊清除機制有所瞭解。
- The End -