自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

超詳細(xì)的PG事務(wù)隔離級(jí)別總結(jié),值得收藏

數(shù)據(jù)庫(kù) 其他數(shù)據(jù)庫(kù)
今天主要介紹一下PG的事務(wù)隔離,事務(wù)隔離和鎖機(jī)制是息息相關(guān)的,希望大家這兩塊都可以掌握。下面先看下SQL標(biāo)準(zhǔn)的四種隔離級(jí)別。

今天主要介紹一下PG的事務(wù)隔離,事務(wù)隔離和鎖機(jī)制是息息相關(guān)的,希望大家這兩塊都可以掌握。下面先看下SQL標(biāo)準(zhǔn)的四種隔離級(jí)別。

超詳細(xì)的PG事務(wù)隔離級(jí)別總結(jié),值得收藏

四種隔離級(jí)別

SQL標(biāo)準(zhǔn)定義了四種隔離級(jí)別。最嚴(yán)格的是可序列化,在標(biāo)準(zhǔn)中用了一整段來(lái)定義它,其中說(shuō)到一組可序列化事務(wù)的任意并發(fā)執(zhí)行被保證效果和以某種順序一個(gè)一個(gè)執(zhí)行這些事務(wù)一樣。其他三種級(jí)別使用并發(fā)事務(wù)之間交互產(chǎn)生的現(xiàn)象來(lái)定義,每一個(gè)級(jí)別中都要求必須不出現(xiàn)一種現(xiàn)象。注意由于可序列化的定義,在該級(jí)別上這些現(xiàn)象都不可能發(fā)生。

在各個(gè)級(jí)別上被禁止出現(xiàn)的現(xiàn)象是:

  • 臟讀:一個(gè)事務(wù)讀取了另一個(gè)并行未提交事務(wù)寫(xiě)入的數(shù)據(jù)。
  • 不可重復(fù)讀:一個(gè)事務(wù)重新讀取之前讀取過(guò)的數(shù)據(jù),發(fā)現(xiàn)該數(shù)據(jù)已經(jīng)被另一個(gè)事務(wù)(在初始讀之后提交)修改。
  • 幻讀:一個(gè)事務(wù)重新執(zhí)行一個(gè)返回符合一個(gè)搜索條件的行集合的查詢(xún), 發(fā)現(xiàn)滿(mǎn)足條件的行集合因?yàn)榱硪粋€(gè)最近提交的事務(wù)而發(fā)生了改變。
  • 序列化異常:成功提交一組事務(wù)的結(jié)果與一次運(yùn)行這些事務(wù)的所有可能順序不一致。

SQL標(biāo)準(zhǔn)和PostgreSQL實(shí)現(xiàn)的事務(wù)隔離級(jí)別如下:

超詳細(xì)的PG事務(wù)隔離級(jí)別總結(jié),值得收藏

事務(wù)隔離級(jí)別

在PostgreSQL中可以請(qǐng)求四種標(biāo)準(zhǔn)事務(wù)隔離級(jí)別中的任意一種。 但是在內(nèi)部,只實(shí)現(xiàn)了三種不同的隔離級(jí)別,即:PostgreSQL的讀未提交模式的行為類(lèi)似于讀已提交。 這是因?yàn)檫@是把標(biāo)準(zhǔn)的隔離級(jí)別映射到PostgreSQL的多版本并發(fā)控制架構(gòu)的唯一合理方法。

要設(shè)置一個(gè)事務(wù)的事務(wù)隔離級(jí)別,使用SET TRANSACTION命令

  1. SET TRANSACTION transaction_mode [, ...] 
  2. SET TRANSACTION SNAPSHOT snapshot_id 
  3. SET SESSION CHARACTERISTICS AS TRANSACTION transaction_mode [, ...] 
  4. where transaction_mode is one of: 
  5.  ISOLATION LEVEL { SERIALIZABLE | REPEATABLE READ | READ COMMITTED | READ UNCOMMITTED } 
  6.  READ WRITE | READ ONLY 
  7.  [ NOT ] DEFERRABLE 

超詳細(xì)的PG事務(wù)隔離級(jí)別總結(jié),值得收藏

1. 讀已提交隔離級(jí)別

讀已提交是PostgreSQL中的默認(rèn)隔離級(jí)別。

當(dāng)一個(gè)事務(wù)運(yùn)行使用這個(gè)隔離級(jí)別時(shí), 一個(gè)查詢(xún)(沒(méi)有FOR UPDATE/SHARE子句)只能看到查詢(xún)開(kāi)始之前已經(jīng)被提交的數(shù)據(jù), 而無(wú)法看到未提交的數(shù)據(jù)或在查詢(xún)執(zhí)行期間其它事務(wù)提交的數(shù)據(jù)。(假設(shè)SQL查詢(xún)了10s,這10s中間插入的新數(shù)據(jù)是看不到的)實(shí)際上,SELECT查詢(xún)看到的是一個(gè)在查詢(xún)開(kāi)始運(yùn)行的瞬間該數(shù)據(jù)庫(kù)的一個(gè)快照。不過(guò)SELECT可以看見(jiàn)在它自身事務(wù)中之前執(zhí)行的更新的效果,即使它們還沒(méi)有被提交。還要注意的是,即使在同一個(gè)事務(wù)里兩個(gè)相鄰的SELECT命令可能看到不同的數(shù)據(jù), 因?yàn)槠渌聞?wù)可能會(huì)在第一個(gè)SELECT開(kāi)始和第二個(gè)SELECT開(kāi)始之間提交。

UPDATE、DELETE、SELECT FOR UPDATE和SELECT FOR SHARE命令在搜索目標(biāo)行時(shí)的行為和SELECT一樣: 它們將只找到在命令開(kāi)始時(shí)已經(jīng)被提交的行。

帶有ON CONFLICT DO UPDATE子句的INSERT的行為類(lèi)似。 在讀已提交模式下,建議插入的每一行都將插入或更新。除非有無(wú)關(guān)的錯(cuò)誤, 否則這兩個(gè)結(jié)果中的一個(gè)是有保證的。如果沖突源于另一個(gè)其影響對(duì)于 INSERT不可見(jiàn)的事務(wù),則將對(duì)該行使用UPDATE子句, 即使可能沒(méi)有命令常規(guī)可見(jiàn)的該行的版本。

帶有ON CONFLICT DO NOTHING子句的INSERT 可能由于其影響對(duì)INSERT快照不可見(jiàn)的另一事務(wù)的結(jié)果而不插入行。 同樣,只有在讀已提交模式下才是這種情況。

因?yàn)樯厦娴囊?guī)則,正在更新的命令可能會(huì)看到一個(gè)不一致的快照: 它們可以看到并發(fā)更新命令在它嘗試更新的相同行上的作用, 但是卻看不到那些命令對(duì)數(shù)據(jù)庫(kù)里其它行的作用。 這樣的行為令讀已提交模式不適合用于涉及復(fù)雜搜索條件的命令。不過(guò), 它對(duì)于更簡(jiǎn)單的情況是正確的。例如,考慮用這樣的命令更新銀行余額:

  1. BEGIN; 
  2. UPDATE accounts SET balancebalance = balance + 100.00 WHERE acctnum = 12345
  3. UPDATE accounts SET balancebalance = balance - 100.00 WHERE acctnum = 7534
  4. COMMIT; 

如果兩個(gè)這樣的事務(wù)同時(shí)嘗試修改帳號(hào) 12345 的余額,那我們很明顯希望第二個(gè)事務(wù)從賬戶(hù)行的已更新版本上開(kāi)始工作。(這里是考慮第二個(gè)update的時(shí)候accounts表數(shù)據(jù)改動(dòng)了)因?yàn)槊總€(gè)命令只影響一個(gè)已經(jīng)決定了的行,讓它看到行的已更新版本不會(huì)導(dǎo)致任何麻煩的不一致性。

因?yàn)樵谧x已提交模式中,每個(gè)命令都是從一個(gè)新的快照開(kāi)始的,而這個(gè)快照包含在該時(shí)刻已提交的事務(wù), 因此同一事務(wù)中的后續(xù)命令將看到任何已提交的并行事務(wù)的效果。以上的焦點(diǎn)在于單個(gè)命令是否看到數(shù)據(jù)庫(kù)的絕對(duì)一致的視圖。

讀已提交模式提供的部分事務(wù)隔離對(duì)于許多應(yīng)用而言是足夠的,并且這個(gè)模式速度快并且使用簡(jiǎn)單。 不過(guò),它不是對(duì)于所有情況都?jí)蛴?。做?fù)雜查詢(xún)和更新的應(yīng)用可能需要比讀已提交模式提供的更嚴(yán)格一致的數(shù)據(jù)庫(kù)視圖。

2. 可重復(fù)讀隔離級(jí)別

可重復(fù)讀隔離級(jí)別只看到在事務(wù)開(kāi)始之前被提交的數(shù)據(jù);它從來(lái)看不到未提交的數(shù)據(jù)或者并行事務(wù)在本事務(wù)執(zhí)行期間提交的修改(不過(guò),查詢(xún)能夠看見(jiàn)在它的事務(wù)中之前執(zhí)行的更新,即使它們還沒(méi)有被提交)。這是比SQL標(biāo)準(zhǔn)對(duì)此隔離級(jí)別所要求的更強(qiáng)的保證,標(biāo)準(zhǔn)只描述了每種隔離級(jí)別必須提供的最小保護(hù)。

這個(gè)級(jí)別與讀已提交不同之處在于,一個(gè)可重復(fù)讀事務(wù)中的查詢(xún)看到 事務(wù)中第一個(gè)非事務(wù)控制語(yǔ)句開(kāi)始時(shí)的一個(gè)快照, 而不是事務(wù)中當(dāng)前語(yǔ)句開(kāi)始時(shí)的快照。 因此,在一個(gè)單一事務(wù)中的后續(xù)SELECT 命令看到的是相同的數(shù)據(jù)(就是我前面說(shuō)的一個(gè)事務(wù)兩個(gè)update那種情況),即它們看不到其他事務(wù)在本事務(wù)啟動(dòng)后提交的修改。

使用這個(gè)級(jí)別的應(yīng)用必須準(zhǔn)備好由于序列化失敗而重試事務(wù)。

UPDATE、DELETE、SELECT FOR UPDATE和SELECT FOR SHARE命令在搜索目標(biāo)行時(shí)的行為和SELECT一樣: 它們將只找到在事務(wù)開(kāi)始時(shí)已經(jīng)被提交的行。 不過(guò),在被找到時(shí),這樣的目標(biāo)行可能已經(jīng)被其它并發(fā)事務(wù)更新(或刪除或鎖住)。在這種情況下, 可重復(fù)讀事務(wù)將等待第一個(gè)更新事務(wù)提交或者回滾(如果它還在進(jìn)行中)。 如果第一個(gè)更新事務(wù)回滾,那么它的作用將被忽略并且可重復(fù)讀事務(wù)可以繼續(xù)更新最初發(fā)現(xiàn)的行。 但是如果第一個(gè)更新事務(wù)提交(并且實(shí)際更新或刪除該行,而不是只鎖住它),則可重復(fù)讀事務(wù)將回滾并帶有如下消息

  1. ERROR: could not serialize access due to concurrent update 

因?yàn)橐粋€(gè)可重復(fù)讀事務(wù)無(wú)法修改或者鎖住被其他在可重復(fù)讀事務(wù)開(kāi)始之后的事務(wù)改變的行。

當(dāng)一個(gè)應(yīng)用接收到這個(gè)錯(cuò)誤消息,它應(yīng)該中斷當(dāng)前事務(wù)并且從開(kāi)頭重試整個(gè)事務(wù)。在第二次執(zhí)行中,該事務(wù)將見(jiàn)到作為其初始數(shù)據(jù)庫(kù)視圖一部分的之前提交的改變,這樣在使用行的新版本作為新事務(wù)更新的起點(diǎn)時(shí)就不會(huì)有邏輯沖突。

注意只有更新事務(wù)可能需要被重試;只讀事務(wù)將永遠(yuǎn)不會(huì)有序列化沖突。

可重復(fù)讀模式提供了一種嚴(yán)格的保證,在其中每一個(gè)事務(wù)看到數(shù)據(jù)庫(kù)的一個(gè)完全穩(wěn)定的視圖。不過(guò),這個(gè)視圖并不需要總是和同一級(jí)別上并發(fā)事務(wù)的某些序列化(一次一個(gè))執(zhí)行保持一致。例如,即使這個(gè)級(jí)別上的一個(gè)只讀事務(wù)可能看到一個(gè)控制記錄被更新,這顯示一個(gè)批處理已經(jīng)被完成但是不能看見(jiàn)作為該批處理的邏輯組成部分的一個(gè)細(xì)節(jié)記錄,因?yàn)樗x取空值記錄的一個(gè)較早的版本。

3. 可序列化隔離級(jí)別

可序列化隔離級(jí)別提供了最嚴(yán)格的事務(wù)隔離。這個(gè)級(jí)別為所有已提交事務(wù)模擬序列事務(wù)執(zhí)行;就好像事務(wù)被按照序列一個(gè)接著另一個(gè)被執(zhí)行,而不是并行地被執(zhí)行。

超詳細(xì)的PG事務(wù)隔離級(jí)別總結(jié),值得收藏

但是,和可重復(fù)讀級(jí)別相似,使用這個(gè)級(jí)別的應(yīng)用必須準(zhǔn)備好因?yàn)樾蛄谢《卦囀聞?wù)。事實(shí)上,這個(gè)給力級(jí)別完全像可重復(fù)讀一樣地工作,除了它會(huì)監(jiān)視一些條件,這些條件可能導(dǎo)致一個(gè)可序列化事務(wù)的并發(fā)集合的執(zhí)行產(chǎn)生的行為與這些事務(wù)所有可能的序列化(一次一個(gè))執(zhí)行不一致。這種監(jiān)控不會(huì)引入超出可重復(fù)讀之外的阻塞,但是監(jiān)控會(huì)產(chǎn)生一些負(fù)荷,并且對(duì)那些可能導(dǎo)致序列化異常的條件的檢測(cè)將觸發(fā)一次序列化失敗。

例如,考慮一個(gè)表mytab,它初始時(shí)包含:

  1. class | value 
  2. ------+------- 
  3. 1 | 10 
  4. 1 | 20 
  5. 2 | 100 
  6. 2 | 200 

假設(shè)可序列化事務(wù) A 計(jì)算:

  1. SELECT SUM(value) FROM mytab WHERE class = 1

并且接著把結(jié)果(3)作為一個(gè)新行的value插入,新行的class = 2。同時(shí),可序列化事務(wù) B 計(jì)算:

  1. SELECT SUM(value) FROM mytab WHERE class = 2

并得到結(jié)果 300,它會(huì)將其與class = 1插入到一個(gè)新行中。然后兩個(gè)事務(wù)都嘗試提交。如果其中一個(gè)事務(wù)運(yùn)行在可重復(fù)讀隔離級(jí)別,兩者都被允許提交;但是由于沒(méi)有執(zhí)行的序列化順序能在結(jié)果上一致,使用可序列化事務(wù)將允許一個(gè)事務(wù)提交并且將回滾另一個(gè)并伴有這個(gè)消息:

  1. ERROR: could not serialize access due to read/write dependencies among transactions 

這是因?yàn)椋绻?A 在 B 之前執(zhí)行,B 將計(jì)算得到合計(jì)值 330 而不是 300,而且相似地另一種順序?qū)?dǎo)致 A 計(jì)算出一個(gè)不同的合計(jì)值。

當(dāng)依賴(lài)可序列化事務(wù)來(lái)阻止異常時(shí),重要的一點(diǎn)是任何從一個(gè)持久化用戶(hù)表讀出數(shù)據(jù)都不被認(rèn)為是有效的,直到讀它的事務(wù)已經(jīng)成功提交為止。即便是對(duì)只讀事務(wù)也是如此,除了在一個(gè)可推遲的只讀事務(wù)中讀取的數(shù)據(jù)是讀出以后立刻有效的,因?yàn)檫@樣的一個(gè)事務(wù)在開(kāi)始讀取任何數(shù)據(jù)之前會(huì)等待,直到它能獲得一個(gè)快照保證來(lái)避免這種問(wèn)題為止。在所有其他情況下,應(yīng)用不能依靠在一個(gè)后來(lái)被中斷的事務(wù)中讀取的結(jié)果;相反,它們應(yīng)當(dāng)重試事務(wù)直到它成功。

要保證真正的可序列化,PostgreSQL使用了謂詞鎖,這意味著它會(huì)保持鎖,這些鎖讓它能夠判斷在它先運(yùn)行的情況下,什么時(shí)候一個(gè)寫(xiě)操作會(huì)對(duì)一個(gè)并發(fā)事務(wù)中之前讀取的結(jié)果產(chǎn)生影響。在PostgreSQL中,這些鎖并不導(dǎo)致任何阻塞,并且因此不會(huì)導(dǎo)致一個(gè)死鎖。它們被用來(lái)標(biāo)識(shí)和標(biāo)志并發(fā)可序列化事務(wù)之間的依賴(lài)性,這些事務(wù)的組合可能導(dǎo)致序列化異常。相反,一個(gè)想要保證數(shù)據(jù)一致性的讀已提交或可重復(fù)讀事務(wù)可能需要拿走一個(gè)在整個(gè)表上的鎖,這可能阻塞其他嘗試使用該表的用戶(hù),或者它可能會(huì)使用不僅會(huì)阻塞其他事務(wù)還會(huì)導(dǎo)致磁盤(pán)訪(fǎng)問(wèn)的SELECT FOR UPDATE或SELECT FOR SHARE。

像大部分其他數(shù)據(jù)庫(kù)系統(tǒng),PostgreSQL中的謂詞鎖基于被一個(gè)事務(wù)真正訪(fǎng)問(wèn)的數(shù)據(jù)。這些謂詞鎖將顯示在pg_locks系統(tǒng)視圖中,它們的mode為SIReadLock。這種在一個(gè)查詢(xún)執(zhí)行期間獲得的特別的鎖將依賴(lài)于該查詢(xún)所使用的計(jì)劃,并且在事務(wù)過(guò)程中多個(gè)細(xì)粒度鎖(如元組鎖)可能和少量粗粒度鎖(如頁(yè)面鎖)相結(jié)合來(lái)防止耗盡用于跟蹤鎖的內(nèi)存。如果一個(gè)READ ONLY事務(wù)檢測(cè)到不會(huì)有導(dǎo)致序列化異常的沖突發(fā)生,它可以在完成前釋放其 SIRead 鎖。事實(shí)上,READ ONLY事務(wù)將常??梢栽趩?dòng)時(shí)確立這一事實(shí)并避免拿到任何謂詞鎖。如果你顯式地請(qǐng)求一個(gè)SERIALIZABLE READ ONLY DEFERRABLE事務(wù),它將阻塞直到它能夠確立這一事實(shí)(這是唯一一種可序列化事務(wù)阻塞但可重復(fù)讀事務(wù)不阻塞的情況)。在另一方面,SIRead 鎖常常需要被保持到事務(wù)提交之后,直到重疊的讀寫(xiě)事務(wù)完成。

可序列化事務(wù)的一致性使用可以簡(jiǎn)化開(kāi)發(fā)。并發(fā)可序列化事務(wù)的任意集合將得到和一次運(yùn)行一個(gè)相同效果的這種保證意味著,如果你能證明一個(gè)單一事務(wù)在獨(dú)自運(yùn)行時(shí)能做正確的事情,則你可以相信它在任何混合的可序列化事務(wù)中也能做正確的事情,即使它不知道那些其他事務(wù)做了些什么。重要的是使用這種技術(shù)的環(huán)境有一種普遍的方法來(lái)處理序列化失敗(總是會(huì)返回一個(gè) SQLSTATE 值 '40001'),因?yàn)樗鼘⒑茈y準(zhǔn)確地預(yù)計(jì)哪些事務(wù)可能為讀/寫(xiě)依賴(lài)性做貢獻(xiàn)并且需要被回滾來(lái)阻止序列化異常。讀/寫(xiě)依賴(lài)性的監(jiān)控會(huì)產(chǎn)生開(kāi)銷(xiāo),如重啟被序列化失敗中止的事務(wù),但是作為在該開(kāi)銷(xiāo)和顯式鎖及SELECT FOR UPDATE或SELECT FOR SHARE導(dǎo)致的阻塞之間的一種平衡,可序列化事務(wù)是在某些環(huán)境中最好性能的選擇。

責(zé)任編輯:趙寧寧 來(lái)源: 今日頭條
相關(guān)推薦

2023-10-13 07:54:49

數(shù)據(jù)庫(kù)MySQL

2019-09-10 07:58:01

字符集MySQL數(shù)據(jù)庫(kù)

2010-11-19 16:13:06

oracle事務(wù)隔離級(jí)

2018-12-19 16:46:38

MySQL事務(wù)隔離數(shù)據(jù)庫(kù)

2009-06-29 17:54:47

Spring事務(wù)隔離

2019-08-13 11:53:01

腳本語(yǔ)言AWKBash

2020-06-19 09:55:00

Redis數(shù)據(jù)庫(kù)字符串

2021-07-26 10:28:13

MySQL事務(wù)隔離

2024-04-26 09:17:20

MySQL事務(wù)隔離

2021-08-04 13:19:42

MySQL 事務(wù)隔離

2019-08-20 09:46:14

DBA收藏腳本語(yǔ)言

2023-10-11 08:09:53

事務(wù)隔離級(jí)別

2021-01-18 11:49:26

面試事務(wù)隔離

2024-12-02 08:37:04

2022-09-13 13:49:05

數(shù)據(jù)庫(kù)隔離

2019-08-06 09:11:49

數(shù)據(jù)庫(kù)數(shù)據(jù)結(jié)構(gòu)操作系統(tǒng)

2025-03-03 08:20:00

MySQL事務(wù)隔離數(shù)據(jù)庫(kù)

2020-10-13 10:32:24

MySQL事務(wù)MVCC

2025-01-13 13:12:54

2021-01-26 09:25:02

Nginx開(kāi)源軟件服務(wù)器
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)