ORA-01555 問題分析(轉)

ningzi82發表於2010-09-17
ORA-01555是常見的oracle錯誤。相信絕大部分dba都遇到過這個錯誤。平時面試的時候我也比較喜歡問這個問題,一方面問題比較基礎, 每個人都有work on it的經驗,可以談談自己的想法,另一方面容易由此問題引申到其他更為複雜一點的問題。平時在論壇上也經常看到有人問這個問題。雖然談論很多了,不過從面 試的結果還有論壇的回帖看,普遍存在下面兩個誤解:[@more@]

1. 為查詢的session指定一個大的回滾段

2. manual管理模式下增大rollback segment的maxextents引數

首先看第一點:為查詢的session指定一個大的回滾段

Ora-01555的常見原因是查詢操作要去讀取的回滾段資訊已經被覆蓋掉,不能完成一致性讀操作(這裡暫時不包含delayed block cleanout的情況了,因為出現比較少,我也沒有在正式環境上遇到過)。注意需要讀取的回滾段資訊不是查詢操作自己寫的回滾段資訊(查詢操作並不寫任 何undo資訊),而是在查詢操作開始後,dml修改操作寫入的undo資訊。理解了這一點,自然明白了為查詢操作指定一個大的回滾段是毫無意義的事情, 因為查詢根本不使用回滾段!

關於第二點,大部分情況下也是沒有作用的

想到第二點的人是想擴大回滾段的大小,但是回滾段的擴充套件只有在回滾段有session沒有commit而導致其不能迴圈使用的時候才會擴充套件。解釋詳 細一點就是session A hold住了回滾段頭並且一直不commit,這時候dml修改操作一直寫回滾段,因為回滾段為環狀結構,寫了一圈下來,Session A還是沒有commit,這時候就會擴充套件回滾段,rbs表空間的剩餘空間和maxextents控制是否能夠擴充套件。ORA-01555的錯誤並不是因為做 dml修改的session不能擴充套件,而是正因為迴圈覆蓋了已經commit的undo資訊導致查詢失敗,因為可以迴圈覆寫。他根本不需要擴充套件。所以增大 maxextents引數大部分情況下不會對ORA-01555錯誤有任何幫助。

下面我來談談自己平時解決ORA-01555錯誤的基本步驟,希望對大家有所幫助

0. 開始先看看rollback segment是否有分配不當的問題,例如某一個rollback segment(報錯的那個)太小。

如果有,先recreate rollback segment以保持所有的回滾段大小一致,並且size不要太小。

1. 看查詢的執行計劃是否正確。ORA-01555錯誤發生的機率和查詢所需的時間成正比,查詢時間越長,發生ORA-01555的機率越大。

如果執行計劃不正確,首先進行sql tuning,如果執行計劃正確,但進行fts,考慮是否可以並行來跑(server load不是很高的情況下)

總之一句話就是儘量縮短query的時間

2. 如果執行計劃正確,估算一下執行時間,如果執行時間不是很長,這時候我喜歡登陸到server本地上執行一下SQL看看需要多少時間

如果本地很快就執行完了,說明問題出在application媏,轉入下面第三點。如果確實很慢,轉入第四點。

3. Application媏的問題可能型別很多,我所遇到的大致有一下幾種

3.1 網路速度太慢,application server和database server的網路出現問題。這時候dba可以從application server端來做一些ping包的測試。

如果確實是網路的問題,可以找網路工程師協助察看是否有網路故障。如果異地之間確實速度很慢,可以考慮是否從一臺速度比較

快的application server上發出查詢請求。

3.2 Cursor open時間太長。有時候application媏是使用open cursor的方式來fetch data。這時候有可能open cursor後長時間不做操作,導致fetch data時

出現ORA-01555。更常見的一種情況是,有些應用是將一些處理程式放置在fetch loop中,例如

declare

cursor cur_query is select object_id from dba_objects;

…..

begin

for i in cur_query loop

….

&do some things here

end loop;

end;

/

這時候可能整個查詢的速度被”&do some things here“這段處理程式的速度所影響,導致整個查詢速度變慢。

可以建議application修改code,將資料先fetch出來存在一個structure中,然後再來處理。

3.3 commiting in a loop,這一點在Tom kyte的Expert Oracle Database Architecture中有詳細的例子(P268),在itpub上有一篇帖子遇到的就是這個問題。

4. 這時候我們要考慮一下資料庫本身了。首先看看產生這麼多undo 資訊是否正常,如果正常的話,考慮是否可以挑選一個系統比較空閒的時段跑查詢。

如果本身查詢執行的時間就是系統比較空閒的時段或者系統從來就沒閒過:), 那就加大回滾段吧。

這裡有兩種方法,

第一種是重建回滾段,修改minextents為一個較大的值,一個一個的offline,drop,create。初始化的大小為minextents*extent size

第二種是增加回滾段的個數

8i在有些情況下oracle會很喜歡用第一個回滾段,不知道為何,可以考慮將第一個回滾段擴大一點(如果錯誤資訊裡面是第一個回滾段的話)

我比較喜歡使用的是第一種方法

5. 如果第四步仍然沒有效果(我們不可能無限制的加大回滾段),那麼可以考慮其他的方法

如果有standby database的話,可以考慮將其open read only來給大的查詢使用,或者為其建立一個報表系統

對於ORA-01555比較頻繁的系統,可以考慮轉為auto management undo tablespace,這樣管理起來簡單一點。

auto管理下處理的基本思想是,獲得最長查詢的時間,預估keep這段時間undo所需的回滾段大小,擴大undo tablespace,修改undo_retention

這裡推薦一篇文章講解auto undo management的文章,講解還是比較詳細的 (右鍵點選下載)

另外關於LOB存在的情況,是完全不同的一種情況,我以前有文章寫過 ,請參考 當ORA-01555遇到了LOB

當然這裡短短的描述還是不能涵蓋ORA-01555 。實際處理問題的時候也不必拘泥於具體的步驟。

理解了基本原理,再輔以實際案例的解決,這樣才會有一個真正意義上的理解。

轉自:http://www.dbafan.com/blog/?p=42

還可參考:

(3).htm

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

相關文章