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