<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中的InnoDB是怎么解決幻讀的?

          共 2089字,需瀏覽 5分鐘

           ·

          2020-09-21 11:11

          點擊上方藍色“程序猿DD”,選擇“設為星標”

          回復“資源”獲取獨家整理的學習資料!

          作者 |?Aaron_濤

          來源 |?blog.csdn.net/qq_33330687/article/details/89004462

          1. 結論

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

          2. 幻讀是什么

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

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

          結果為:

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

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

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

          commit;

          事務A,然后再select一下:

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

          結果集為:

          … 11,uu …

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

          這次是已提交事務B對事務A產生的影響,這個影響叫做“幻讀”。

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

          3. 怎么解決的?

          3.1. 當前讀

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

          拿上面那個例子來說,在RR的情況下,假設使用的是當前讀,加鎖了的讀

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

          3.2. 普通讀

          因為普通讀是不會加鎖的讀,故不會有next-key locks的使用,解決幻讀的手段是MVCC

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

          而每一個事務在啟動的時候,都有一個唯一的遞增的版本號。每開啟一個新事務,事務的版本號就會遞增。

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

          SELECT

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

          INSERT

          • 將當前事務的版本號保存至行的創(chuàng)建版本號

          UPDATE

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

          DELETE

          • 將當前事務的版本號保存至行的刪除版本號

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

          如果我更新的話,事務id假設是2

          這里是把name更新為taotao,原來的元組deleteversion版本號為這個事務的id,并且新增一條

          如果我刪除的話,假設事務是id=3? ? ? ??

          ? ? ?

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

          關鍵點來了

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

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

          就拿上面那個例子說明

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

          假設事務A的id=10

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

          事務B的id=11

          insert into table values(11, uu);

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

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

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

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

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

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

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

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

          4. 多說一句

          在RC的模式下,MVCC解決不了幻讀和不可重復讀,因為每次讀都會讀它自己刷新的快照版本,簡單來說就是另一個事務提交,他就刷新一次,去讀最新的

          其他資料

          https://segmentfault.com/a/1190000012669504


          往期推薦

          Redis為什么變慢了?常見延遲問題定位與分析

          為什么 GROUP BY 之后不能直接引用原表中的列?

          Java開發(fā)中Websocket的技術選型參考

          為什么MySQL不推薦使用uuid或者雪花id作為主鍵?

          用鴻蒙跑了個 “hello world”!鴻蒙開發(fā)初體驗


          我們在星球聊了很多深度話題,你不來看看?

          我的星球是否適合你?

          點擊閱讀原文看看我們都聊過啥?

          瀏覽 81
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <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>
                  亚洲国产精品久久久久久 | 日本黄色视频网站在线观看 | 在线观看亚 | 日本午夜福利 | 天天看片中文字幕 |