<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          三分鐘圖解事務(wù)隔離級別,看一遍就懂

          共 2496字,需瀏覽 5分鐘

           ·

          2021-10-11 11:35

          前文說過,“鎖" 是數(shù)據(jù)庫系統(tǒng)區(qū)別于文件系統(tǒng)的一個關(guān)鍵特性,其對象是事務(wù),用來鎖定的是數(shù)據(jù)庫中的對象,如表、頁、行等。鎖確實(shí)提高了并發(fā)性,但是卻不可避免地存在一些潛在的并發(fā)一致性問題

          不過好在鎖只會帶來四種問題(丟失更新、臟讀、不可重復(fù)讀、幻讀),如果可以防止這四種情況的發(fā)生,那將不會產(chǎn)生并發(fā)異常。為此,ISO 和 ANIS SQL 標(biāo)準(zhǔn)制定了四種事務(wù)隔離級別標(biāo)準(zhǔn),用來對應(yīng)地解決鎖帶來的幾種問題。

          鎖帶來的四種并發(fā)一致性問題

          丟失更新 Last To Modify

          丟失更新非常好理解,簡單來說其就是一個事務(wù)的更新操作會被另一個事務(wù)的更新操作所覆蓋,從而導(dǎo)致數(shù)據(jù)的不一致。

          舉個例子:

          1)事務(wù) T1 將行記錄 r 更新為 v1,但是事務(wù) T1 并未提交

          2)與此同時,事務(wù) T2 將行記錄 r 更新為 v2,事務(wù) T2 未提交

          3)事務(wù) T1 提交

          4)事務(wù) T2 提交

          如下圖所示,顯然,事務(wù) T1 丟失了自己的修改。

          但是,事實(shí)上,這種情況準(zhǔn)確來講并不會發(fā)生。

          因?yàn)槲覀冋f過對于行進(jìn)行更新操作的時候,需要對行或其他粗粒度級別的對象加鎖,因此當(dāng)事務(wù) T1 修改行 r 但是沒提交的時候,事務(wù) T2 對行 r 進(jìn)行更新操作的時候是會被阻塞住的,直到事務(wù) T1 提交釋放鎖。

          所以,從數(shù)據(jù)庫層面來講,數(shù)據(jù)庫本身是可以幫助我們阻止丟失更新問題的發(fā)生的

          不過,在真實(shí)的開發(fā)環(huán)境中,我們還經(jīng)常會遇到邏輯意義上的丟失更新。舉個例子:

          1)事務(wù) T1 查詢一行數(shù)據(jù) r,放入本地內(nèi)存,并顯示給一個用戶 User1

          2)事務(wù) T2 也查詢該行數(shù)據(jù),并將取得的數(shù)據(jù)顯示給另一個用戶 User2

          3)User1 修改了行記錄 r 為 v1,更新數(shù)據(jù)庫并提交

          4)User2 修改了行記錄 r 為 v2,更新數(shù)據(jù)庫并提交

          顯然,最終這行記錄的值是 v2,User1 的更新操作被 User2 覆蓋掉了,丟失了他的修改。

          可能還是云里霧里,我來舉個更現(xiàn)實(shí)點(diǎn)的例子吧,一個部門共同查看一個在線文檔,員工 A 發(fā)現(xiàn)自己的性別信息有誤,于是將其從 “女” 改成了 “男”,就在這時,HR 也發(fā)現(xiàn)了員工 A 的部門信息有誤,于是將其從 ”測試“ 改成了 ”開發(fā)“,然后,員工 A 和 HR 同時點(diǎn)了提交,但是 HR 的網(wǎng)絡(luò)稍微慢一點(diǎn),再次刷新,員工 A 就會發(fā)現(xiàn),擦,我的性別怎么還是 ”女“?

          臟讀 Dirty Read

          所謂臟讀,就是說一個事務(wù)讀到了另外一個事務(wù)中的 "臟數(shù)據(jù)",臟數(shù)據(jù)就是指事務(wù)未提交的數(shù)據(jù)

          如下圖所示,在事務(wù)并沒有提交的前提下,事務(wù) T1 中的兩次 SELECT 操作取得了不同的結(jié)果:

          注意,如果想要再現(xiàn)臟讀這種情況,需要把隔離級別調(diào)整在 Read UnCommitted(讀取未提交)。所以事實(shí)上臟讀這種情況基本不會發(fā)生,因?yàn)楝F(xiàn)在大部分?jǐn)?shù)據(jù)庫的隔離級別都至少設(shè)置成 READ COMMITTED

          不可重復(fù)讀 Unrepeatableread

          不可重復(fù)讀是指在一個事務(wù)內(nèi)多次讀取同一數(shù)據(jù)集合。在這個事務(wù)還沒有結(jié)束時,另外一個事務(wù)也訪問該同一數(shù)據(jù)集合,并做了一些修改操作。因此,在第一個事務(wù)中的兩次讀數(shù)據(jù)之間,由于第二個事務(wù)的修改,那么第一個事務(wù)兩次讀到的數(shù)據(jù)可能是不一樣的

          舉個例子:事務(wù) T1 讀取一行數(shù)據(jù) r,T2 將該行數(shù)據(jù)修改成了 v1。如果 T1 再次讀取這行數(shù)據(jù),此時讀取的結(jié)果和第一次讀取的結(jié)果是不同的

          不可重復(fù)讀和臟讀的區(qū)別是:臟讀是讀到未提交的數(shù)據(jù),而不可重復(fù)讀讀到的卻是已經(jīng)提交的數(shù)據(jù),但是其違反了事務(wù)一致性的要求。

          幻讀 Phantom Read

          幻讀本質(zhì)上是屬于不可重復(fù)讀的一種情況,區(qū)別在于,不可重復(fù)讀主要是針對數(shù)據(jù)的更新(即事務(wù)的兩次讀取結(jié)果值不一樣),而幻讀主要是針對數(shù)據(jù)的增加或減少(即事務(wù)的兩次讀取結(jié)果返回的數(shù)量不一樣)

          舉個例子:事務(wù) T1 讀取某個范圍的數(shù)據(jù),事務(wù) T2 在這個范圍內(nèi)插入了一些新的數(shù)據(jù),然后 T1 再次讀取這個范圍的數(shù)據(jù),此時讀取的結(jié)果比第一次讀取的結(jié)果返回的記錄數(shù)要多

          四種事務(wù)隔離級別標(biāo)準(zhǔn)

          SQL 標(biāo)準(zhǔn)定義了四種越來越嚴(yán)格的事務(wù)隔離級別,用來解決我們上述所說的四種事務(wù)的并發(fā)一致性問題。

          1)READ UNCOMMITTED 讀取未提交:事務(wù)中的修改,即使沒有提交,對其它事務(wù)也是可見的。

          上面提到過,數(shù)據(jù)庫本身其實(shí)已經(jīng)具備阻止丟失更新的能力,也就是說,即使是最低的隔離級別也可以阻止丟失更新問題。所以:

          • 這個隔離級別可以阻止 丟失更新

          2)READ COMMITTED 讀取已提交:一個事務(wù)只能讀取已經(jīng)提交的事務(wù)所做的修改。換句話說,一個事務(wù)所做的修改在提交之前對其它事務(wù)是不可見的。

          • 這個隔離級別可以阻止 丟失更新 + 臟讀

          3)REPEATABLE READ 可重復(fù)讀(InnoDB 存儲引擎默認(rèn)的隔離級別):保證在同一個事務(wù)中多次讀取同一數(shù)據(jù)的結(jié)果是一樣的

          • 這個隔離級別可以阻止 丟失更新 + 臟讀 + 不可重復(fù)讀

          4)SERIALIZABL 可串行化:強(qiáng)制事務(wù)串行執(zhí)行(需要使用鎖機(jī)制來實(shí)現(xiàn)),這樣多個事務(wù)互不干擾,不會出現(xiàn)并發(fā)一致性問題。

          • 這個隔離級別可以阻止 丟失更新 + 臟讀 + 不可重復(fù)讀 + 幻讀

          可以看到四種隔離級別能阻止的并發(fā)一致性問題越來越多,但并不代表越高的隔離級別就越好,因?yàn)槭聞?wù)隔離級別越高,數(shù)據(jù)庫付出的性能代價也就相應(yīng)地越大。


          另外,多提一嘴,InnoDB 存儲引擎在 REPEATABLE READ 事務(wù)隔離級別下,使用 Next-Key Lock 鎖的算法避免了幻讀的產(chǎn)生。也就是說,InnoDB 存儲引擎在其默認(rèn)的 REPEATABLE READ 事務(wù)隔離級別下就已經(jīng)能完全保證事務(wù)的隔離性要求了,即達(dá)到了 SQL 標(biāo)準(zhǔn)的 SERIALIZABLE 隔離級別。


          流水不爭先,爭的是滔滔不絕,我是小牛肉,小伙伴們下篇文章再見 ??

          瀏覽 31
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  精品人妻一区二区三区含羞草 | 婷婷丁香五月天影院亚洲综合桃花 | 无码爱爱网站 | 国内一级黄片 | 亚洲最大视频网站 |