innodb next-key lock引發的死鎖現象分析
這個例子是我在網上看到的,我分析了很久才弄明白鎖產生的具體過程。
資料庫的事務隔離級別是RR。
建測試表:
CREATE TABLE `LockTest` (
`order_id` varchar(20) NOT NULL,
`id` bigint(20) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`),
KEY `idx_order_id` (`order_id`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8;
測試步驟:
測試結果:
事務1 執行到insert語句會block住,事務2執行insert語句會提示死鎖錯誤。
原因分析:
1、首先看測試表的建表語句,id是主鍵索引,同時該主鍵是自增主鍵。order_id是普通索引。
2、事務1執行delete from LockTest where order_id = 'D20';語句時,由於資料庫的隔離級別是RR,因此此時事務1在主鍵id上獲得了一個next-key lock,這個鎖的範圍是[16, +∞)。
這個16就來自於AUTO_INCREMENT=16,因為LockTest目前是張空表。
3、同理,事務2執行delete from LockTest where order_id = 'D19';語句時,由於資料庫的隔離級別是RR,事務2在主鍵id上也獲得了一個next-key lock,這個鎖的範圍是[16, +∞)。
也就是說此時,事務1和事務2獲得的鎖是一樣的。
4、事務1繼續執行insert into LockTest (order_id) values ('D20');語句,這個時候由於該語句企圖往LockTest表insert一行id=16,order_id=D20的資料,
但是由於在事務2的delete語句中,主鍵id上已經有了一個範圍為[16, +∞)的鎖,導致事務1此時想插入資料插不進去,被阻塞了。
5、繼續事務2的插入語句insert into LockTest (order_id) values ('D19'); 該插入語句同樣也想往LockTest表insert一行id=16,order_id=D19的資料,
但是由於由於在事務1的delete語句中,主鍵id上已經有了一個範圍為[16, +∞)的鎖,導致事務2此時想插入資料插不進去,被阻塞了。
此時,可以發現,事務1和事務2的鎖是互相持有,互相等待的。所以innodb判斷該事務遇到了死鎖,直接將事務2進行了回滾。然後回頭去看事務1,insert into LockTest (order_id) values ('D20');被成功執行。
如果你將資料庫的事務隔離級別修改為RC,上述事務會各自成功執行,不會互相影響。
資料庫的事務隔離級別是RR。
建測試表:
CREATE TABLE `LockTest` (
`order_id` varchar(20) NOT NULL,
`id` bigint(20) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`),
KEY `idx_order_id` (`order_id`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8;
測試步驟:
事務1 | 事務2 |
begin delete from LockTest where order_id = 'D20' |
|
begin delete from LockTest where order_id = 'D19' |
|
insert into LockTest (order_id) values ('D20') |
|
insert into LockTest (order_id) values ('D19') |
|
commit |
commit |
測試結果:
事務1 執行到insert語句會block住,事務2執行insert語句會提示死鎖錯誤。
原因分析:
1、首先看測試表的建表語句,id是主鍵索引,同時該主鍵是自增主鍵。order_id是普通索引。
2、事務1執行delete from LockTest where order_id = 'D20';語句時,由於資料庫的隔離級別是RR,因此此時事務1在主鍵id上獲得了一個next-key lock,這個鎖的範圍是[16, +∞)。
這個16就來自於AUTO_INCREMENT=16,因為LockTest目前是張空表。
3、同理,事務2執行delete from LockTest where order_id = 'D19';語句時,由於資料庫的隔離級別是RR,事務2在主鍵id上也獲得了一個next-key lock,這個鎖的範圍是[16, +∞)。
也就是說此時,事務1和事務2獲得的鎖是一樣的。
4、事務1繼續執行insert into LockTest (order_id) values ('D20');語句,這個時候由於該語句企圖往LockTest表insert一行id=16,order_id=D20的資料,
但是由於在事務2的delete語句中,主鍵id上已經有了一個範圍為[16, +∞)的鎖,導致事務1此時想插入資料插不進去,被阻塞了。
5、繼續事務2的插入語句insert into LockTest (order_id) values ('D19'); 該插入語句同樣也想往LockTest表insert一行id=16,order_id=D19的資料,
但是由於由於在事務1的delete語句中,主鍵id上已經有了一個範圍為[16, +∞)的鎖,導致事務2此時想插入資料插不進去,被阻塞了。
此時,可以發現,事務1和事務2的鎖是互相持有,互相等待的。所以innodb判斷該事務遇到了死鎖,直接將事務2進行了回滾。然後回頭去看事務1,insert into LockTest (order_id) values ('D20');被成功執行。
如果你將資料庫的事務隔離級別修改為RC,上述事務會各自成功執行,不會互相影響。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/28497416/viewspace-2141147/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- innodb_lock_monitor解決mysql死鎖MySql
- Mysql加鎖過程詳解(8)-理解innodb的鎖(record,gap,Next-Key lock)MySql
- mysql innodb的行鎖(5) --next-Key 鎖MySql
- 模擬SQLserver死鎖現象SQLServer
- MYSQL INNODB replace into 死鎖 及 next key lock 淺析MySql
- 面試:什麼是死鎖,如何避免或解決死鎖;MySQL中的死鎖現象,MySQL死鎖如何解決面試MySql
- mysql innodb lock鎖之record lock之一MySql
- MySQL innodb 的間隙鎖定(next-key locking)MySql
- 單一會話引發的死鎖會話
- MySQL next-key lock 加鎖範圍是什麼?MySql
- MySQL自增鎖模式innodb_autoinc_lock_mode引數詳解MySql模式
- MySQL:Innodb 一個死鎖案例MySql
- MySQL InnoDB如何應付死鎖MySql
- MySQL Next-Key LockMySql
- Mysql加鎖過程詳解(9)-innodb下的記錄鎖,間隙鎖,next-key鎖MySql
- Oracle中的死鎖Dead Lock(一)Oracle
- Oracle中的死鎖Dead Lock(二)Oracle
- [CareerCup] 16.4 A Lock Without Deadlocks 無死鎖的鎖
- 死鎖分析
- mysql-innodb 日誌機制分析----寫在死鎖前面MySql
- MySQL:一個死鎖分析 (未分析出來的死鎖)MySql
- MySQL 5.5 -- innodb_lock_wait 鎖 等待MySqlAI
- SQLSERVER 語句交錯引發的死鎖研究SQLServer
- SQLServer的死鎖分析(1):頁鎖SQLServer
- 死鎖案例分析
- HashMap死鎖分析HashMap
- 使用oracle 10704 event分析獲取鎖lock及死鎖deadlock系列九Oracle
- MySQL自增列鎖模式 innodb_autoinc_lock_mode不同引數下效能測試MySql模式
- 鎖:innodb_lock_wait_timeout和 innodb_rollback_on_timeout?AI
- mysql死鎖deadlock相關幾個系統變數innodb_lock_wait_timeoutMySql變數AI
- 【JavaSE】Lock鎖和synchronized鎖的比較,lock鎖的特性,讀寫鎖的實現。Javasynchronized
- 不合理的執行順序引發的死鎖
- MYSQL中一個特殊的MDL LOCK死鎖案列MySql
- GreatSQL 死鎖案例分析SQL
- TX鎖(Transaction Lock)分析 (zt)
- InnoDB 事務加鎖分析
- 故障分析 | MySQL死鎖案例分析MySql
- MySQL/InnoDB中,樂觀鎖、悲觀鎖、共享鎖、排它鎖、行鎖、表鎖、死鎖概念的理解MySql