隔离级别是 RR ,这里 c_id 是一个普通索引,(c_id, d_id) 是一个唯一索引。
transaction1 | transaction2 |
---|---|
BEGIN; delete from demo where c_id = 'abc';Query OK, 0 rows affected (0.00 sec) |
|
BEGIN; delete from demo where c_id = 'xyz';Query OK, 0 rows affected (0.00 sec) |
|
insert into demo (c_id , d_id ) values ('abc', '111'), ('abc', '222'), ('abc', '333');WAITING |
|
insert into demo (c_id , d_id ) values ('xyz', '444'), ('xyz', '555'), ('xyz', '666');ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction |
最终事务 1 被回滚了。
死锁的日志关键字:
(1) WAITING FOR THIS LOCK TO BE GRANTED
lock_mode X locks gap before rec insert intention waiting
(2) TRANSACTION:
TRANSACTION 947943174, ACTIVE 0 sec updating or deleting
mysql tables in use 1, locked 1
(2) HOLDS THE LOCK(S):
RECORD LOCKS space id 899935 page no 578533 n bits 200 index c_id_index of table `demo` trx id 947943174 lock_mode X
(2) WAITING FOR THIS LOCK TO BE GRANTED:
lock_mode X locks rec but not gap waiting
原因基本很明确:应该是两个 delete 同时获取了 gap 或 next_key 锁,然后因为不存在记录,导致锁的范围很大,甚至是一个 ∞ 的区间,同时 insert 语句无法获取插入意向锁,并互相等待引发死锁。(这样理解对吗)
不能改变隔离级别。
是否先查一下要删除的条件有没有记录,如果有,再执行删除。这样是否就可以了。
Thank you!
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.