Oracle數據庫的經典問題 snapshot too old是什么原因引起的
ORACLE經典錯誤求解:ORA-1555錯誤(Snapshot too old ) - ...
書上說是因為the rollback image need for read consistency has prbably been overwriteten by an active transaction. 我就奇怪了,如果一個transaction占用了一些回滾段,直到它commit前,這些回滾段空間應該被鎖定了呀,怎么會被其他transaction覆蓋了呢?
--------------------------
rollback segment 太小
--------------------------
snapshot too old 就是指你commit,前鏡像被覆蓋以后 如果有查詢需要訪問這個前鏡像構建一致性讀,就會導致ORA-01555錯誤
-----------------------------
加大你的undo segment 的 initial extents 值, 盡量減少warp,當然undo file 要夠大:) -------------------------
A. 回滾段太少/太小 導致這個錯誤,可以 創建更多的回滾段, 為回滾段設置較大的EXTENT以及較大的MINEXTENTS B.由於回滾段被破壞, 造成事務無法將修改前的內容(read-consistent snapshot) 放入回滾段, 也會產生此錯誤. 可以將被破壞的回滾段OFFLINE, 刪除重建. C. 當一個進程打開一個CURSOR, 然後迴圈執行FETCH, UPDATE, COMMIT, 如果更新的表與FETCH的是同一個表, 就很可能發生此錯誤. 解決方法: a. 使用大的回滾段 ,b. 減少提交頻率c. 建立一個臨時表, 存放要更新的表的查詢列(如主鍵及相關的條件列), 從臨時表FETCH, 更新原來的表. D. 不適當的OPTIMAL參數: 太小的OPTIMAL參數會使回滾段很快被SHRINK, 造成後續讀取操作訪問時, 先前的內容已丟失. 仔細設計OPTIMAL參數, 不要讓回滾段過於頻繁的EXTEND/SHRINK有助於問題的解決. E. DB BLOCK BUFFER太小: 如果讀一致性所請求的塊的先前內容在緩衝區中, 那麼就不用去訪問回滾段. 而如果緩衝區太小, 使得先前版本的內容在CACHE中的可能性變小, 從而必須頻繁的訪問回滾段來獲取先前的內容, 這將大大增大此錯誤發生的可能.
----------------------------
假設你的emp表很大,你在18:00運行
select * from emp;
這個語句的輸出結果應該只取決於18:00的時候emp表的數據狀態,但事實上,由於emp表很大,你這個語句可能要運行10分鍾,然后才看到輸出結果
在18:01,有人在emp表上做了一個update,update直接做到表上了,怎樣使你18:00運行的select還能看到之前的數據呢?oracle用的是查詢前映的辦法,即把update之前的數據放到回滾段里保存,使你的select在查詢到那個block的時候,會跳轉去找前映,這樣可以使你的select能正確運行下去。
但可能發生這種情況,就是做update的人commit了,於是前映就有可能在被你的select訪問到之前被覆蓋,假如真的發生了這種情況,snapshot too old的錯誤就出現了 ------------------------
這也說明了你的SQL執行得太慢了,需要調整,在9i中有一個undo_retention參數,假設期指定1小時,那么超過1小時的SQL就容易出現snapshot too old的錯誤了。 -----------------------------
----------------------------
MySQL不會出現這種問題