【发布时间】:2013-03-14 15:04:12
【问题描述】:
我发现了一个非常令人困惑的死锁情况,需要帮助才能理解。
有两个交易正在进行:
(2) 持有查询delete from myTable where id = NAME_CONST('p_id',10000) 的锁。这是 PRIMARY KEY 的锁,虽然不是完整的密钥,而是一个范围。当它说lock_mode X locks rec but not gap时,这对我来说似乎是一个完整的写锁。
(1) 正在等待同一个锁,也等待查询delete from myTable where id = NAME_CONST('p_id',10000)。
(2) 也在尝试获取这个锁,MySQL 检测到死锁。
我无法理解的是为什么 (2) 必须再次获取锁,因为它已经持有它并且在所有情况下它都是一个写锁 (lock_mode X)。
它看起来也适用于完全相同的查询。
这是表定义
create myTable (
id int unsigned not null,
value1 char(8) not null,
value2 int unsigned,
primary key (id, value1)
);
这是来自SHOW ENGINE INNODB STATUS\G的信息
------------------------
LATEST DETECTED DEADLOCK
------------------------
130313 14:46:28
*** (1) TRANSACTION:
TRANSACTION 75ACB8A3, ACTIVE 0 sec, process no 6110, OS thread id 139973945382656 starting index read
mysql tables in use 1, locked 1
LOCK WAIT 2 lock struct(s), heap size 376, 1 row lock(s)
MySQL thread id 5154970, query id 5201313618 192.168.0.2 user updating
delete from myTable where id = NAME_CONST('p_id',10000)
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 22371 page no 1598 n bits 104 index `PRIMARY` of table `db`.`myTable` trx id 75ACB8A3 lock_mode X waiting
Record lock, heap no 32 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
0: len 4; hex 0005af3a; asc :;;
1: len 8; hex 2020202020202020; asc ;;
2: len 6; hex 000075acb890; asc u ;;
3: len 7; hex ea0000020d011e; asc ;;
4: len 4; hex 00000065; asc e;;
*** (2) TRANSACTION:
TRANSACTION 75ACB890, ACTIVE 0 sec, process no 6110, OS thread id 139973957895936 starting index read
mysql tables in use 1, locked 1
7 lock struct(s), hea
p size 1248, 6 row lock(s), undo log entries 4
MySQL thread id 5155967, query id 5201313625 192.168.0.1 user updating
delete from myTable where id = NAME_CONST('p_id',10000)
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 22371 page no 1598 n bits 104 index `PRIMARY` of table `db`.`myTable` trx id 75ACB890 lock_mode X locks rec but not gap
Record lock, heap no 32 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
0: len 4; hex 0005af3a; asc :;;
1: len 8; hex 2020202020202020; asc ;;
2: len 6; hex 000075acb890; asc u ;;
3: len 7; hex ea0000020d011e; asc ;;
4: len 4; hex 00000065; asc e;;
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 22371 page no 1598 n bits 104 index `PRIMARY` of table `db`.`myTable` trx id 75ACB890 lock_mode X waiting
Record lock, heap no 32 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
0: len 4; hex 0005af3a; asc :;;
1: len 8; hex 2020202020202020; asc ;;
2: len 6; hex 000075acb890; asc u ;;
3: len 7; hex ea0000020d011e; asc ;;
4: len 4; hex 00000065; asc e;;
*** WE ROLL BACK TRANSACTION (1)
【问题讨论】:
-
您是否尝试重现错误?如果“是”,你能告诉我们场景吗?
-
我已经尝试使用
start transaction; delete...; rollback;从两个模拟线程中尽可能快地执行此删除操作,就像 bash 可以将其提供给 mysql 一样快,但我一次都没有遇到死锁。我完全不知道这是怎么发生的。 -
请参阅这个问题(它描述了如何捕获死锁):stackoverflow.com/questions/2143873/…。还有一篇关于检测和恢复死锁的好文章:dwachira.hubpages.com/hub/…。一般来说,死锁是架构和设计的问题。您应该检查更新数据的流程。
-
也许我不够清楚。我已经对死锁了解很多。它们是什么,它们如何出现以及如何防止它们。这次我的问题是我不明白为什么事务 (2) 需要获取它已经持有的锁。这可能更多的是关于 innoDB 的问题,而不是一般的死锁。
-
生产数据库上
show variables like '%autocommit%'的结果是什么?
标签: mysql transactions innodb deadlock