引自http://blog.csdn.net/lanbaibai/archive/2004/06/29/29547.aspx
讀已提交(Read Committed)
當一個事務運行在這個隔離級別時, 一個SELECT 查詢只能看到查詢開始之前提交的數據而永遠無法看到未提交的數據或者是在查詢執行時其他并行的事務提交做的改變。(不過SELECT 的確看得見同一次事務中前面更新的結果.即使它們還沒提交也看得到.)實際上,一個SELECT 查詢看到一個在該查詢開始運行的瞬間該數據庫地一個快照。請注意兩個相鄰的SELECT 可能看到不同的數據,哪怕它們是在同一個事務里,因為其它事務會在第一個SELECT執行的時候提交.
讀已提交隔離級別
讀已提交(Read Committed) 是 PostgreSQL 里的缺省隔離級別。 當一個事務運行在這個隔離級別時, 一個 SELECT 查詢只能看到查詢開始之前提交的數據而永遠無法看到未提交的數據或者是在查詢執行時其他并行的事務提交做的改變。 (不過 SELECT 的確看得見同一次事務中前面更新的結果。即使它們還沒提交也看得到。) 實際上,一個 SELECT 查詢看到一個在該查詢開始運行的瞬間該數據庫的一個快照。 請注意兩個相鄰的 SELECT 命令可能看到不同的數據,哪怕它們是在同一個事務里, 因為其它事務會在第一個SELECT執行的時候提交.
UPDATE, DELETE, 或者 SELECT FOR UPDATE 在搜索目標行的時候的行為和SELECT 一樣: 它們只能找到在命令開始的時候已經提交的行。 不過,這樣的目標行在被找到的時候可能已經被其它并發的事務更新(或者刪除,或者標記為更新的)。 在這種情況下,即將進行的更新將等待第一個更新事務提交或者回滾(如果它還在處理)。 如果第一個更新回滾,那么它的作用將被忽略,而第二個更新者將繼續更新最初發現的行。 如果第一個更新者提交,那么如果第一個更新者刪除了該行,則第二個更新者將忽略該行, 否則它將試圖在該行的已更新的版本上施加它的操作。系統將重新計算命令搜索條件(WHERE 子句), 看看該行已更新的辦不那是否仍然符合搜索條件。如果是,則第二個更新繼續其操作,從該行的已更新版本開始。
因為上面的規則,正在更新的命令可能會看到不一致的快照 --- 它們可以看到影響它們試圖更新的并發更新命令的效果, 但是它們看不到那些命令對數據庫里其它行的作用。 這樣的行為令讀已提交模式不適合用于哪種涉及復雜搜索條件的命令。 不過,它對于簡單的情況而言是正確的。比如,假設我們用類似下面這樣的命令更新銀行余額:
BEGIN; UPDATE accounts SET balance = balance + 100.00 WHERE acctnum = 12345; UPDATE accounts SET balance = balance - 100.00 WHERE acctnum = 7534; COMMIT;如果兩個并發事務試圖修改帳號 12345 的余額,那我們很明顯希望第二個事務是從帳戶行的已經更新過的版本上進行更新。 因為每個命令只是影響一個已經決定了的行,因此讓它看到更新后的版本不會導致任何不一致的問題。
因為在讀已提交模式里,每個新的命令都是從一個新的快照開始的,而這個快照包含所有到該時刻為止已經提交的事務, 因此同一個事務里的后面的命令將看到任何已提交的并發事務的效果。 這里要考慮的問題是我們在一個命令里是否看到數據庫里絕對一致的視圖。
讀已提交模式提供的部分事務隔離對于許多應用而言是足夠的,并且這個模式速度快,使用簡單。 不過,對于做復雜查詢和更新的應用,可能需要保證數據庫有比讀已提交模式提供的更加嚴格的一致性視圖。
12.2.2. 可串行化隔離級別
可串行化(Serializable) 級別提供最嚴格的事務隔離。 這個級別模擬串行的事務執行, 就好象事務將被一個接著一個那樣串行的,而不是并行的執行。 不過,使用這個級別的應用必須準備在串行化失敗的時候重新發動事務.
當一個事務處于可串行化級別, 一個 SELECT 查詢只能看到在事務開始之前提交的數據而永遠看不到未提交的數據或事務執行中其他并行事務提交的修改。 (不過,SELECT 的確看得到同一次事務中前面的更新的效果。即使事務還沒有提交也一樣。) 這個行為和讀已提交級別是不太一樣,它的 SELECT 看到的是該事務開始時的快照,而不是該事務內部當前查詢開始時的快照。 這樣,一個事務內部后面的 SELECT 命令總是看到同樣的數據。
UPDATE, DELETE,和 SELECT FOR UPDATE 在搜索目標行上的行為和 SELECT 一樣: 它們將只尋找在事務開始的時候已經提交的目標行。但是, 這樣的目標行在被發現的時候可能已經被另外一個并發的事務更新了(或者是刪除或者是標記為更新)。 在這種情況下,可串行化的事務將等待第一個正在更新的事務提交或者回滾(如果它仍然在處理中)。 如果第一個更新者回滾,那么它的影響將被忽略, 而這個可串行化的就可以繼續更新它最初發現的行。 但是如果第一個更新者提交了(并且實際上更新或者刪除了該行,而不只是為更新選中它)那么可串行化事務將回滾,并返回下面信息
ERROR: Can't serialize access due to concurrent update因為一個可串行化的事務在可串行化事務開始之后不能更改被其他事務更改過的行。
當應用收到這樣的錯誤信息時,它應該退出當前的事務然后從頭開始重新進行整個事務。 第二次運行時,該事務看到的前一次提交的修改是該數據庫初始的樣子中的一部分, 所以把新版本的行作為新事務更新的起點不會有邏輯沖突。
請注意只有更新事務才需要重試,只讀事務從來沒有串行化沖突.
可串行化事務級別提供了嚴格的保證:每個事務都看到一個完全一致的數據庫的視圖。 不過,如果并行更新令數據庫不能維持串行執行的樣子,那么應用必須準備重試事務。 因為重做復雜的事務的開銷可能是非常可觀的,所以我們只建議在更新命令中包含足夠復雜的邏輯, 在讀已提交級別中可能導致錯誤的結果的情況下才使用。 最常見的是,可串行化模式只是在這樣的情況下是必要的:一個事務連續做若干個命令, 而這幾個命令必須看到數據庫完全一樣的視圖。
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/lanbaibai/archive/2004/06/29/29547.aspx
posted on 2009-12-06 11:39
zhqh 閱讀(97)
評論(0) 編輯 收藏 所屬分類:
數據庫