天天看點

mysql 鎖_五分鐘了解mysql間隙鎖

0x01:什麼是間隙鎖

間隙鎖(Gap Lock)是Innodb在可重複讀送出下為了解決幻讀問題時引入的鎖機制。當用範圍條件而不是相等條件檢索資料,并請求共享或排他鎖時,InnoDB會給符合條件的已有資料記錄的索引項加鎖;對于鍵值在條件範圍内但不存在的記錄,叫做“間隙(GAP)”,InnoDB也會對這些“間隙”進行加鎖,這種鎖機制就是所謂的間隙鎖(NEXT-KEY)鎖。

0x02:間隙鎖引起的問題

因為執行SELECT語句中,如果通過範圍查找的話,間隙鎖會鎖定整個範圍内所有的索引鍵值,即使這個鍵值并不存在。這個就是間隙鎖最緻命的缺點,就是當鎖定一個範圍鍵值之後,即使某些不存在的鍵值也會被無辜的鎖定,而造成在鎖定的時候無法插入鎖定值範圍内的任何資料,在某些場景下這可能會針對性造成很大的危害。

0x03:間隙鎖例子

建表:

CREATE TABLE `gas_lock_tab` (`id`  bigint(20) NOT NULL COMMENT 'id' ,`user_name_py`  int(11) NOT NULL COMMENT '使用者姓名拼音' ,PRIMARY KEY (`id`),INDEX `usernameIndex` (`user_name_py`) USING BTREE )ENGINE=InnoDBDEFAULT CHARACTER SET=utf8 COLLATE=utf8_general_ciROW_FORMAT=DYNAMIC;
           

插入資料:

INSERT INTO `gas_lock_tab`(`id`, `user_name_py`) VALUES (1, 'huangjinjin');INSERT INTO `gas_lock_tab`(`id`, `user_name_py`) VALUES (3, 'java樂園');INSERT INTO `gas_lock_tab`(`id`, `user_name_py`) VALUES (5, '架構師知音');INSERT INTO `gas_lock_tab`(`id`, `user_name_py`) VALUES (8, 'java狂人');   
           

插入資料後查詢:

mysql> select * from gas_lock_tab;+----+--------------+| id | user_name_py |+----+--------------+|  1 | huangjinjin  ||  3 | java樂園     ||  8 | java狂人     ||  5 | 架構師知音    |+----+--------------+4 rows in set  
           

注意表中的資料,id字段是int型,包含1,3,5,8;當然1到8中間,缺少連續的id:2,4,6,7,而沒有連續下來。一般在表裡的主鍵id最好是連續的,友善索引;所謂的删除其實是做邏輯删除,隻是做了狀态更改,而不做實體删除。

打開兩個Mysql終端,分别設定autocommit為0(手動送出事務),也就是關閉自動送出功能,事務隔離級别處于可重複讀狀态。

session 1:

mysql> set autocommit=0;Query OK, 0 rows affected
           
mysql 鎖_五分鐘了解mysql間隙鎖

session 2:

mysql> set autocommit=0;Query OK, 0 rows affected
           
mysql 鎖_五分鐘了解mysql間隙鎖

session 1 執行update操作,執行成功

mysql> update gas_lock_tab set user_name_py = '1234' where id > 1 and id 
           

也就是對3這四條資料做修改。注意這裡沒有id為2和4的記錄;在第二個終端執行insert操作,發現被阻塞。

insert into gas_lock_tab values (2,'it大佬');
           
mysql 鎖_五分鐘了解mysql間隙鎖

按說在InnoDB的行級鎖,兩個不同的終端操作不同的行資料,不會造成阻塞,但是阻塞出現了。達到逾時時間後,seesion 2出現如下錯誤:

mysql 鎖_五分鐘了解mysql間隙鎖

另外,如果在session 2的插入語句沒有逾時之前,對session 1進行 commit操作,則會發現session 2也會執行操作成功。

session 1 commit操作:

mysql 鎖_五分鐘了解mysql間隙鎖

session 2出現的結果:

mysql 鎖_五分鐘了解mysql間隙鎖

這時對session 1做commit操作,發現update和inster操作都生效了。

mysql 鎖_五分鐘了解mysql間隙鎖