【MySQL】鎖入門

要作的徹底掌握MySQL/InnoDB的加鎖規則,甚至是其餘任何數據庫的加鎖規則,須要具有如下的一些知識點數據庫

  1. 瞭解數據庫的一些基本理論知識:數據的存儲格式 (堆組織表 vs 聚簇索引表);併發控制協議 (MVCC vs Lock-Based CC);Two-Phase Locking;數據庫的隔離級別定義 (Isolation Level);
  2. 瞭解SQL自己的執行計劃 (主鍵掃描 vs 惟一鍵掃描 vs 範圍掃描 vs 全表掃描);
  3. 瞭解數據庫自己的一些實現細節 (過濾條件提取;Index Condition Pushdown;Semi-Consistent Read);
  4. 瞭解死鎖產生的緣由及分析的方法 (加鎖順序不一致;分析每一個SQL的加鎖順序)

有了這些知識點,再加上適當的實戰經驗,全面掌控MySQL/InnoDB的加鎖規則,當不在話下。併發

最近開始關注MySQL的鎖問題,也但願開始對鎖有個大概的認識,今天從簡單的概念入手;通常分爲2種,一種是DML操做時的鎖機制,另外一種,則是在DDL操做時,鎖是如何來進行控制的。學習

做爲學習的開始,仍是先從簡單的入手比較合適,因此,這裏做爲一個入門級的第一篇文章,先簡單介紹下DML中涉及到的讀寫鎖,即便如此,也仍是在實際實驗中,遇到了和理論不一致的狀況,暫時還不能給你們拿出合理解釋,下面給出詳情:code

  1. 共享鎖和排它鎖索引

    InnoDB支持最小粒度到數據行的行級鎖:事務

    • 共享鎖,容許事務經過持有共享鎖去讀取一行
    • 排他鎖,容許事務經過持有排它鎖去更新或者刪除一行

    一行數據,能夠容許多個事務同時持有共享鎖,可是隻能有一個事務持有排他鎖,若是另外一個事務也須要持有排他鎖,則須要等待以前持有該鎖的事務,釋放掉鎖get

  2. 意向鎖it

    InnoDB除行級鎖之外,還在表級別,添加了一種叫作意向鎖的概念,其表示事務即將對該表的某些行作讀或者寫操做io

    • 共享意向鎖,表示某事務即將要對該表的某些行數據加共享鎖
    • 排它意向鎖,表示某事務即將要對該表的某些行數據加排他鎖

    舉個例子:入門

    select ... lock in share mode 將在表上持有IS共享意向鎖,select for update則是在表上持有IX排他意向鎖
    

    意向鎖的兩個使用規約:

    • 事務在持有表上某行數據的行共享鎖以前,必須先持有表上的共享意向鎖,或者級別更高的排他意向鎖
    • 事務在持有表上某行數據的行排他鎖以前,必須先持有表上的排他意向鎖

    表級別的意向鎖和行級別的鎖,排斥關係以下:

      X IX S IS
    X Conflict Conflict Conflict Conflict
    IX Conflict Compatible Conflict Compatible
    S Conflict Conflict Compatible Compatible
    IS Conflict Compatible Compatible Compatible

    舉一個例子:

    事務A執行了select lock in share mode ,這時,事務A持有了IS鎖和S鎖(爲啥要加上 lock in share mode 呢?不加,就是快照讀,不會要求去持有鎖,反過來,利用lock in share mode,能夠在業務上實現原子讀寫操做哦,你們能夠本身思考一下) 事務B要在相同的行上,執行update 語句,那麼這時,事務B首先要去持有表級別的IX鎖,根據上圖第2行最後一列,IX 和 IS 是共享的,因此,這個沒問題。而後,事務B要對相同的行,作寫操做,因此其須要持有X鎖,根據上圖第1行第3列,X和S是不兼容的,因此事務B須要等待事務A結束之後,才能執行。

    • 反思1:若是事務A使用select for update,事務B會如何反映?(結果同樣,事務B會等待事務A結束)
    • 反思2:若是事務B,update不一樣的行,事務B會如何反映?(結果不同,事務B不須要等待事務A)
    • 反思3:若是根據第一行第三列的規則,豈不是一個事務作了update操做,另外一個事務就不能讀了?寫阻塞讀?(其實讀,都是快照讀,並不會要求持有S鎖)
  3. 行級鎖

    行級鎖老是針對某個索引記錄進行加鎖,用以防止其餘事物併發對當前加鎖的行進行讀取和修改。因此,及時用戶沒有定義任何索引和主鍵,MySQL也會在內部,自動生成一個隱含的主鍵列。 行級鎖,其目的,就是爲了保證多個事務不能同時對相同的一條數據執行修改動做

  4. 間隙鎖

    間隙鎖,顧名思義,其鎖定的是若干個索引記錄的某個範圍(不包括記錄自己),好比:SELECT c1 FROM t WHERE c1 > 10 and c1 < 20 FOR UPDATE; 這個就鎖定了10~20的這個範圍(10.20),防止其餘事物,插入c1的值在10~20直接的記錄,但c1等於10或者c1等於20,則是容許被插入的 如上SQL所示,間隙表跟行級鎖的一個區別在於,間隙鎖是鎖定了一個區間範圍,防止別人對這個區間內的數據,執行insert或者update。

    小實驗:

    假如在索引列上,事務A執行的是 c1 between 10 and 20 for update,那麼,事務B可以插入c1等於10(或者20)的記錄嗎?

  5. Next-Key鎖

    接上一個問題,假如事務A執行的是 c1 between 10 and 20 for update,那麼,除了鎖定10,20的區間之外,還須要鎖定記錄自己(10和20),這就是Next-Key鎖: Next-Key就是間隙鎖的一種升級,其鎖定的內容,除了範圍之外,還包含記錄的自己,好比,C1這個普通索引列上,有3條數據:1,10,20,30,那麼,可能存在的Next-Key的鎖有如下幾種(區間 + 記錄):(無限小,1]. (1,10]. (10,20] . (20,30]. (30,無限大)

    當執行select * from A where c1 between 10 and 20 for update時,其加上的鎖:爲:(1,10],(10,20],(20,30),其範圍會擴大到當前Key的下一個值中去,你會發現,在事務B中,c1 >1 到C1 < 30 的記錄,所有不容許插入,而不只僅是10到20直接。

  6. 自增鎖

    表級別,還有一個特殊的鎖:自增鎖,後面的文章,將給出詳細介紹。

參考: MySQL 加鎖處理分析

相關文章
相關標籤/搜索