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