1. 程式人生 > 其它 >34.Mysql怎樣加鎖淺談01

34.Mysql怎樣加鎖淺談01

1.前言

  本小結屬於怎樣判斷innodb內部怎樣加鎖的,資料innodb的核心篇,也是非常重要的一節

2.加鎖的規則

  兩個原則、兩個優化、一個bug --->這裡的預設隔離級別是:可重複讀隔離級別

  • 原則1:加鎖的基本單位是next-key-lock,是前開後閉區間
  • 原則2: 查詢過程中訪問到的物件才會加鎖
  • 優化1: 索引上的等值查詢,給唯一索引加鎖的時候,next-key-lock退化為行鎖。 
  • 優化2: 索引上的等值查詢,向右遍歷時且最後一個值不滿足等值條件的時候,next-key lock退化為間隙鎖。
  • 一個bug: 唯一索引上的範圍查詢會訪問到不滿足條件的第一個值為止。   

3.案例

  這裡先建立一個表 

CREATE TABLE `t` (
  `id` int(11) NOT NULL,
  `c` int(11) DEFAULT NULL,
  `d` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `c` (`c`)
) ENGINE=InnoDB;

insert into t values(0,0,0),(5,5,5),
(10,10,10),(15,15,15),(20,20,20),(25,25,25);

  案例一:等值查詢間隙鎖

  

分析:

  由於id=7用的是唯一索引(主鍵索引),且id=7是在id=5和id=10之間,因此根據原則1,加鎖規則是next-key lock,索引加鎖的區間是(5,10];

  然後再根據優化2:索引上進行等值查詢時,向右遍歷時且最後一個值不滿足等值條件的時候,next-key lock退化為間隙鎖,因此此時索引加鎖區間是(5,10)

  案例二:非唯一索引等值鎖

  

分析:

  1.此時看到c是普通索引

  2.根據原則1:加鎖的單位是next-key lock,因此此時加鎖區間是(0,5],又因此c是普通索引,所以還需要向右遍歷,查到c=10才放棄。因此根據原則2,訪問到的都要加鎖,因此需要給(5,10]

   加上next-key lock

  3.但是同時這個符合優化 2:等值判斷,向右遍歷,最後一個值不滿足 c=5 這個等值條件,因此退化成間隙鎖 (5,10),因此最終的加鎖區間是(0,5]和(5,10)

  案例三:主鍵索引範圍鎖

  

分析:

  1.開始執行的時候,要找到第一個id=10的行,因此本該是next-key lock(5,10].根據優化1,主鍵id上的等值條件,退化為行鎖,只加了id=10這一行的行鎖。

  2.範圍查詢就往後繼續找,找到id=15這一行停下來,因此需要加next-key lock(10,15].

  所以,session A這時候鎖的範圍就是主鍵索引上,行鎖id=10和next-key lock(10,15].這樣session B和session C的結果你就能理解了。

  案例四:非唯一索引範圍鎖

  

分析:

  1.注意此時的約束條件時c欄位

  2.這次session A用欄位c來判斷,加鎖規則跟案例三唯一不同的是:在第一次用c=10定位記錄的時候,索引c上加了(5,10]這個next-key lock之後,由於索引c是非唯一索引,沒有優化規則,也就是說不會蛻變為行鎖,因此最終session A加的鎖是,索引c上的(5,10]和(10,15]這兩個next-key lock.

  所以從結果上來看,session B要插入(8,8,8)的這個insert 語句時就被堵住了。

  這裡需要掃描到c=15才停止掃描,是合理的,因為innodb要掃到c=15,才知道不需要繼續往後找了。