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

          面試突擊:MVCC 和間隙鎖有什么區(qū)別?

          共 2747字,需瀏覽 6分鐘

           ·

          2023-06-04 13:20

          8d6a4d707b9bd7b5b9a951f46ddab9c5.webp

          作者 | 磊哥

          來源 | Java中文社群(ID:javacn666)

          轉(zhuǎn)載請聯(lián)系授權(quán)(微信ID:GG_Stone)

          MVCC 和間隙鎖是兩種完全不同的機制,但它們的目的都是相同的,都是用來保證數(shù)據(jù)庫并發(fā)訪問的,我們先來看二者的定義。

          MVCC 定義

          MVCC 是多版本并發(fā)控制(Multi-Version Concurrency Control)的縮寫,是一種并發(fā)控制的方法。

          在 MVCC 中,每個讀操作會看到一個固定版本的數(shù)據(jù)庫記錄,即使在并發(fā)環(huán)境中,也不會出現(xiàn)讀取到了其他事務(wù)還未提交的數(shù)據(jù)的情況。

          MVCC 通過保存數(shù)據(jù)在某個時間點的快照來實現(xiàn)這一點。在讀取數(shù)據(jù)時,只會讀取在該時間點之前提交的數(shù)據(jù)。在寫入數(shù)據(jù)時,會為每個寫入操作創(chuàng)建一個新版本的數(shù)據(jù),而不是直接覆蓋原有的數(shù)據(jù)。這樣,讀操作就可以讀取舊版本的數(shù)據(jù),而寫操作則可以寫入新版本的數(shù)據(jù),從而實現(xiàn)了并發(fā)控制。

          在 MySQL 中,InnoDB 存儲引擎就是使用 MVCC 來實現(xiàn)并發(fā)控制的。

          間隙鎖定義

          間隙鎖是一種鎖定索引范圍而非實際數(shù)據(jù)的鎖,它可以鎖定一個范圍,防止其他事務(wù)在這個范圍內(nèi)插入數(shù)據(jù),從而保證了范圍內(nèi)的數(shù)據(jù)的唯一性。在 MySQL 中,InnoDB 存儲引擎支持間隙鎖。當(dāng)使用 SELECT ... FOR UPDATE 或 SELECT ... LOCK IN SHARE MODE 語句時,InnoDB 存儲引擎會自動使用間隙鎖來鎖定索引范圍。

          如果一個事務(wù)在一個間隙上持有了鎖,那么其他事務(wù)就不能在這個間隙上插入數(shù)據(jù),但是可以在這個間隙之前或之后的位置插入數(shù)據(jù)。

          為什么要有 MVCC?

          既然已經(jīng)有鎖可以防止并發(fā)訪問了,那為什么還需要 MVCC 呢?MVCC 的誕生主要是出于性能的考慮,因為 MVCC 中沒有用到鎖,它是通過多版本并發(fā)控制的手段來實現(xiàn)數(shù)據(jù)庫并發(fā)訪問的,這樣相比于加鎖性能就會好很多。

          MVCC 實現(xiàn)原理

          MVCC 竟然這么強,那它是怎么實現(xiàn)的呢?簡單來說 MVCC 是通過以下 3 大組件實現(xiàn)的:

          1. 隱藏字段:每個執(zhí)行的 SQL 命令都有幾個隱藏的字段,其中有一個事務(wù) ID 字段,很重要。
          2. undo log(回滾日志):里面記錄了 SQL 命令執(zhí)行的歷史數(shù)據(jù)。
          3. Read View(讀視圖):包含快照讀(一個快照,保存了數(shù)據(jù)庫某個時刻的數(shù)據(jù))和一些重要的屬性。

          它的實現(xiàn)原理簡單來說,是通過 SQL 中隱藏的字段事務(wù) ID(自己的版本號)和 Read View 中的屬性版本號進行對比,對比之后決定使用 Read View 中的快照或 undo log 中的歷史數(shù)據(jù)(對比的規(guī)則是 MVCC 機制的規(guī)定,本文不展開討論),最后再將符合的數(shù)據(jù)返回。

          MVCC 可以解決幻讀嗎?

          幻讀是指在一個事務(wù)中,第一次查詢某個范圍的數(shù)據(jù)時,發(fā)現(xiàn)有一些數(shù)據(jù)符合條件,但是當(dāng)再次查詢同樣的范圍時,卻發(fā)現(xiàn)多了一些或者少了一些數(shù)據(jù)。這種情況就被稱為幻讀。幻讀是由于并發(fā)事務(wù)中的數(shù)據(jù)修改操作導(dǎo)致的,比如在一個事務(wù)中,另一個事務(wù)插入了一條符合條件的數(shù)據(jù),導(dǎo)致第二次查詢時多了一條數(shù)據(jù)。

          MVCC 機制可以解決部分幻讀問題,MVCC 是通過保存數(shù)據(jù)在某個時間點的快照來實現(xiàn)來解決(部分)幻讀問題的,在讀取數(shù)據(jù)時,MVCC 會根據(jù)快照來確定可見的數(shù)據(jù)版本。這樣,即使其他事務(wù)在讀取數(shù)據(jù)時進行了修改,也不會影響當(dāng)前事務(wù)的讀取結(jié)果。

          因此,MVCC 可以有效地解決這部分幻讀問題。但需要注意的是,MVCC 只能解決讀取數(shù)據(jù)時的幻讀問題,對于寫入數(shù)據(jù)時的幻讀問題,還需要配合鎖機制或使用更高的事務(wù)隔離級別(串行化)來解決。

          也就是說,想要徹底解決 MySQL InnoDB 中 RR(REPEATABLE READ,可重復(fù)讀)事務(wù)隔離級別的幻讀問題,需要使用 MVCC + 鎖機制共同來實現(xiàn)。

          鎖分類

          在 MySQL InnoDB 中的鎖機制不止有間隙鎖,還有行鎖和臨建鎖等。

          行鎖、間隙鎖和臨建鎖有什么區(qū)別?

          行鎖、間隙鎖和臨建鎖都是 MySQL 中的鎖機制,它們的區(qū)別如下:

          • 行鎖是針對某一行數(shù)據(jù)進行的鎖定,可以防止其他事務(wù)修改該行數(shù)據(jù)。
          • 間隙鎖是針對某一范圍的數(shù)據(jù)進行的鎖定,可以防止其他事務(wù)在該范圍內(nèi)插入數(shù)據(jù)。
          • 臨建鎖是行鎖和間隙鎖的組合,可以理解為一種特殊的間隙鎖,它等于行鎖+間隙鎖,除了鎖住記錄本身,還會鎖住索引之間的間隙,即鎖定一段左開右閉的索引區(qū)間。

          小結(jié)

          MVCC 和鎖機制解決了 MySQL InnoDB 中 RR 事務(wù)隔離級別的幻讀問題,而 MySQL 中的鎖類型又有很多種,如行鎖、間隙鎖、臨建鎖等。

          最后

          磊哥 32 萬字的《Java面試突擊:2023版》新鮮出爐,其中包含了:Spring Cloud、Spring Boot、Dubbo、Nacos、Sentinel、ZooKeeper、Kafka、RabbitMQ、設(shè)計模式、MyBatis、網(wǎng)絡(luò)、MySQL、Redis、并發(fā)編程、JVM、Java 基礎(chǔ)等模塊的常見面試題~ 歡迎掃碼訂閱,前 200 名加入的朋友,贈送價值 99 元的簡歷輔導(dǎo),名額有限,抓緊行動吧。


          瀏覽 67
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

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

          手機掃一掃分享

          分享
          舉報
          <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>
                  www.久久综合 | 欧美成人在线观看网站 | 天天爽天天干成人av | 91久久网 | 天堂中文在线资源 |