<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>

          面試官:你說熟悉MySQL,那來談?wù)処nnoDB怎么解決幻讀的?

          共 1941字,需瀏覽 4分鐘

           ·

          2020-09-25 03:46


          作者:Aaron_濤

          blog.csdn.net/qq_33330687/article/details/89004462

          1. 結(jié)論

          首先說結(jié)論,在RR的隔離級(jí)別下,Innodb使用MVCC和next-key locks解決幻讀,MVCC解決的是普通讀(快照讀)的幻讀,next-key locks解決的是當(dāng)前讀情況下的幻讀。

          2. 幻讀是什么

          事務(wù)A,先執(zhí)行:

          update?table?set?name=“hh”?where?id>3;

          結(jié)果為:

          OK row xx 表名成功影響多少行數(shù)據(jù)

          事務(wù)B,后執(zhí)行,并且提交:

          insert?into?table?values(11,?uu);

          commit;

          事務(wù)A,然后再select一下:

          select?*?from?table?where?id>3

          結(jié)果集為:

          …11,uu…

          事務(wù)A懵了,我特么不是id>3全部更新了嗎

          這次是已提交事務(wù)B對(duì)事務(wù)A產(chǎn)生的影響,這個(gè)影響叫做“幻讀”。

          幻讀和不可重復(fù)讀的區(qū)別是,前者是一個(gè)范圍,后者是本身

          3. 怎么解決的?

          3.1. 當(dāng)前讀

          所謂當(dāng)前讀,指的是加鎖的select(S或者X), update, delete等語句。在RR的事務(wù)隔離級(jí)別下,數(shù)據(jù)庫會(huì)使用next-key locks來鎖住本條記錄以及索引區(qū)間。

          拿上面那個(gè)例子來說,在RR的情況下,假設(shè)使用的是當(dāng)前讀,加鎖了的讀

          select * from table where id>3?鎖住的就是id=3這條記錄以及id>3這個(gè)區(qū)間范圍,鎖住索引記錄之間的范圍,避免范圍間插入記錄,以避免產(chǎn)生幻影行記錄。

          搜索Java知音公眾號(hào),回復(fù)“后端面試”,送你一份Java面試題寶典.pdf

          3.2. 普通讀

          因?yàn)槠胀ㄗx是不會(huì)加鎖的讀,故不會(huì)有next-key locks的使用,解決幻讀的手段是MVCC

          MVCC會(huì)給每行元組加一些輔助字段,記錄創(chuàng)建版本號(hào)和刪除版本號(hào)。

          而每一個(gè)事務(wù)在啟動(dòng)的時(shí)候,都有一個(gè)唯一的遞增的版本號(hào)。每開啟一個(gè)新事務(wù),事務(wù)的版本號(hào)就會(huì)遞增。

          默認(rèn)的隔離級(jí)別(REPEATABLE READ)下,增刪查改變成了這樣:

          SELECT

          • 讀取創(chuàng)建版本小于或等于當(dāng)前事務(wù)版本號(hào),并且刪除版本為空或大于當(dāng)前事務(wù)版本號(hào)的記錄。這樣可以保證在讀取之前記錄是存在的

          INSERT

          • 將當(dāng)前事務(wù)的版本號(hào)保存至行的創(chuàng)建版本號(hào)

          UPDATE

          • 新插入一行,并以當(dāng)前事務(wù)的版本號(hào)作為新行的創(chuàng)建版本號(hào),同時(shí)將原記錄行的刪除版本號(hào)設(shè)置為當(dāng)前事務(wù)版本號(hào)

          DELETE

          • 將當(dāng)前事務(wù)的版本號(hào)保存至行的刪除版本號(hào)

          比如我插入一條記錄, 事務(wù)id 假設(shè)是1 ,那么記錄如下:也就是說,創(chuàng)建版本號(hào)就是事務(wù)版本號(hào)。

          如果我更新的話,事務(wù)id假設(shè)是2

          這里是把name更新為taotao,原來的元組deleteversion版本號(hào)為這個(gè)事務(wù)的id,并且新增一條

          如果我刪除的話,假設(shè)事務(wù)是id=3? ? ? ??

          ? ? ?

          就變成現(xiàn)在這個(gè)樣子

          關(guān)鍵點(diǎn)來了

          現(xiàn)在我讀取的話,必須同時(shí)滿足兩個(gè)條件的

          • 讀取創(chuàng)建版本小于或等于當(dāng)前事務(wù)版本號(hào) ? 這意味著數(shù)據(jù)在這個(gè)事務(wù)之前被創(chuàng)建
          • 刪除版本為空或大于當(dāng)前事務(wù)版本號(hào)的記錄。?這意味著刪除操作在這個(gè)事務(wù)之后發(fā)生

          就拿上面那個(gè)例子說明

          當(dāng)前數(shù)據(jù)庫的狀態(tài)

          假設(shè)事務(wù)A的id=10

          現(xiàn)在update table set name=“hh” where id>3;執(zhí)行這條語句

          事務(wù)B的id=11

          insert into table values(11, uu);

          最后事務(wù)A(id=10)在此讀取

          select?*?from?table?where?id>3

          根據(jù)上述的規(guī)則,讀取創(chuàng)建版本好小于等于當(dāng)前事務(wù)的→那么(4,a)(5,b)(4,hh)(5,hh)

          上面規(guī)則的輸出作為下面規(guī)則的輸入的話,刪除版本為空或大于當(dāng)前事務(wù)版本號(hào)的記錄→(4,hh)(5,hh)

          如此讀取就沒有讀取到事務(wù)B新插入的那行,解決幻讀

          如果事務(wù)B是更新id=4 的元組name=cc呢

          同理,根據(jù)update的規(guī)則

          然后根據(jù)select的規(guī)則去讀取的話,得到的還是(4,hh)(5,hh)

          4. 多說一句

          在RC的模式下,MVCC解決不了幻讀和不可重復(fù)讀,因?yàn)槊看巫x都會(huì)讀它自己刷新的快照版本,簡(jiǎn)單來說就是另一個(gè)事務(wù)提交,他就刷新一次,去讀最新的

          其他資料

          https://segmentfault.com/a/1190000012669504



          更多精彩文章


          瀏覽 61
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

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

          手機(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>
                  A片视频免费播放 | 成人91AV电影 | 日韩无码,123。 | 影音先锋乱伦电影 | 亚洲专区免费 |