閱讀文本大概須要3分鐘。java
0x01:什麼是間隙鎖mysql
間隙鎖(Gap Lock)是Innodb在可重複讀提交下爲了解決幻讀問題時引入的鎖機制。當用範圍條件而不是相等條件檢索數據,並請求共享或排他鎖時,InnoDB會給符合條件的已有數據記錄的索引項加鎖;對於鍵值在條件範圍內但不存在的記錄,叫作「間隙(GAP)」,InnoDB也會對這些「間隙」進行加鎖,這種鎖機制就是所謂的間隙鎖(NEXT-KEY)鎖。程序員
0x02:間隙鎖引發的問題web
由於執行SELECT語句中,若是經過範圍查找的話,間隙鎖會鎖定整個範圍內全部的索引鍵值,即便這個鍵值並不存在。這個就是間隙鎖最致命的缺點,就是當鎖定一個範圍鍵值以後,即便某些不存在的鍵值也會被無辜的鎖定,而形成在鎖定的時候沒法插入鎖定值範圍內的任何數據,在某些場景下這可能會針對性形成很大的危害。sql
0x03:間隙鎖例子
微信
建表:
session
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=InnoDB
DEFAULT CHARACTER SET=utf8 COLLATE=utf8_general_ci
ROW_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狂人');
插入數據後查詢:
app
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
session 2:
mysql> set autocommit=0;
Query OK, 0 rows affected
session 1 執行update操做,執行成功
mysql> update gas_lock_tab set user_name_py = '1234' where id > 1 and id < 5;
Query OK, 0 rows affected
Rows matched: 1 Changed: 0 Warnings: 0
也就是對3這四條數據作修改。注意這裏沒有id爲2和4的記錄;在第二個終端執行insert操做,發現被阻塞。
insert into gas_lock_tab values (2,'it大佬');
按說在InnoDB的行級鎖,兩個不一樣的終端操做不一樣的行數據,不會形成阻塞,可是阻塞出現了。達到超時時間後,seesion 2出現以下錯誤:
另外,若是在session 2的插入語句沒有超時以前,對session 1進行 commit操做,則會發現session 2也會執行操做成功。
session 1 commit操做:
session 2出現的結果:
這時對session 1作commit操做,發現update和inster操做都生效了。
☆
往期精彩
☆
關注我
天天進步一點點
本文分享自微信公衆號 - JAVA樂園(happyhuangjinjin88)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。