oracle隔離級別深究追根

jinqibingl發表於2015-02-13

oracle資料庫,只有兩種隔離級別:read committed和serializable。
簡單的說,read committed是語句級隔離,serializable是事務級隔離,read committed意思是指,在你運算元據期間,就是指事務期間,可以看到別人操作commit的結果,serializable是指運算元據期間,就是事務期間,看不到別人操作commit的結果,簡單的將,就是在事務開始的時候,給做了一個快照一樣,別人在同一個表裡的操作commit是看不到的。
serializable是最高階別的事務隔離,一般來說,應該是非常重要或者極其重要的資料,在長時間或者較長時間內處理的時候,不希望自己正在處理的資料被改變,有人說,我們不是在處理資料的時候,加上鎖了嗎?怎麼還會被改變呢,實際情況是,確實會被改變,這是因為oracle預設隔離級別是read committed,阻止髒讀(看不到別人未提交的資料),但是不阻止非重複讀和幻象。
一、先考慮隔離級別對select查詢的影響。
serializable隔離級別,是事務級隔離,按照這個概念,在事務開始或者將事務隔離級別確定為serializable後,就確定了SCN,然後根據這個SCN和系統SCN比對,來確定查詢是否進入撤銷段。
也就是說,隔離級別是否對select有影響,如何影響,在這個事務期間,能否看到和自己事務不衝突的“其他人動過”的資料。這個有待於驗證。
已經驗證,在連線後,事務隔離級別更改為serializable後,確實無法看不到別人commit的操作結果,應該可以確定,在事務隔離級別更改後,本事務就被隔離,完全看不到別人的操作,也就是說,已經給資料庫拍了個快照,這時候事務能看到的是一個靜態的資料庫。
二、隔離級別serializable引發衝突
serializable是最高隔離級別,對資料的操作要求非常霸道,針對同一行資料時,通俗的講,就是我update或者delete(insert估計沒有影響)這行資料的時候,任何其他使用者不能動,動了的話,我就直接報錯。
現在假定,事務1(read committed隔離)對A行資料更新,不提交,然後事務2(serializable隔離)對A行資料更新,這時候鎖定機制存在,事務2開始等待。下一步,事務1,使用commit提交。介面再回到事務2上,就是發現,報錯ora08177,這就是說,事務2的serializable隔離級別,要求我在開始運算元據的時候,不允許別人運算元據,由於預設髒讀已經被隔離,所以這裡指的不允許別人運算元據的動作應該是commit,而不是dml動作。
這裡可以看出一點,serializable隔離級別,好像很不喜歡鎖排隊機制,上面的舉例,是每次都準確的,也就是說,serializable隔離級別的事務,一旦被阻塞,需要排隊等待鎖,那麼有50%或者更高的機率會報錯,這是因為dml操作的最後結果有兩個:commit和rollback。按照概念上的理解,rollback應該不會引發錯誤。
三、serializable隔離級別的用途
serializable是最高的隔離級別,針對的應該是非常重要或者及其重要的資料,或者說要求查詢出來的結果,在事務期間,多個查詢結果必須完全一致,不能被其他使用者變動,這樣的要求可以使用serializable隔離級別,其他一般用途建議還是使用預設隔離級別。
serializable隔離級別,考慮應該是為了保持隔離,也就是徹底隔離別個使用者對本使用者的影響,或者從使用者角度看,就是我先完成事務,其他事務才能繼續,實際情況只是這個使用者被完全隔離,完全看不到別個使用者所做的操作。
四、serializable隔離級別的缺點
1是這種隔離級別,需要的撤銷資料會增加很多,從實際情況看,在事務確定更改隔離級別為serializable後,系統可能會檢測到有高隔離級別事務存在,從而增加需要儲存的撤銷資料,以便能夠提供一個讀一致性快照,這個要注意的是,這個讀一致性快照,是一個全面性的快照,也就是說很可能的是,因為serializable隔離級別事務存在,很多撤銷段,狀態是unexpired,不過期,就是事務已經提交,但是因為讀一致性要求,資料庫希望這個撤銷段繼續保持,不重寫。在一個高併發的資料庫中,長時間或者較長時間存在一個serializable隔離級別的事務,意味著資料庫可能認為需要提供一個很長時間保持存在的讀一致性快照,從而進一步增加撤銷空間,這樣會浪費伺服器資源,可能導致其他使用者事務停止或者非常緩慢,或者導致dml無法執行,因為無法擴充套件撤銷段或者指定撤銷段(撤銷段全被serializable隔離級別使用的讀一致性快照佔用)。
2是serializable隔離級別,在這個事務期間,如果有dml操作,那麼就會導致這個事務等待,從而可能這個事務dml操作失敗,也就是ora08177。網路上的ora08177錯誤,往往是一個測試,或者一個表,但是如果實際操作中,serializable隔離級別的事務,長時間或者較長時間存在,那麼實際情況比測試更加嚴重,因為這個高隔離級別的事務,可能針對多個表進行dml操作,同時可能和多個使用者發生ora08177錯誤。
五、serializable隔離級別
從實際測試可以看出,serializable隔離級別,其實際目的是想當某個特定使用者,在某個特定時間,在一個高併發、資料改變頻繁的資料庫裡面,能夠看到一個靜態的、不發生改變的資料庫,也就是一個大的資料快照。
實際用途應該是結算、或者資料轉移等等,也就是,業務要求,我在操作期間,資料不要改變,這時候可以使用serializable隔離級別,這種高隔離級別的事務,要結合你所擁有的伺服器資源考慮,來考慮其事務執行時間,要切記不要長時間保持這種高隔離級別事務的存在,因為時間一長,撤銷資料就增加很快,資源消耗,會導致資料庫效能下降,影響其他使用者體驗。

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

相關文章