我有一张很简单的桌子:
CREATE TABLE `d` (
`id` int(11) DEFAULT NULL,
UNIQUE KEY `id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
无记录:
select * from d;
Empty set (0,01 sec)
然后我尝试在不同的会话中打开两个事务:
课程1:
begin;
Query OK, 0 rows affected (0,00 sec)
select * from d where id = 100 for update;
Empty set (0,00 sec)
第2节:
begin;
Query OK, 0 rows affected (0,00 sec)
select * from d where id = 700 for update;
Empty set (0,00 sec)
现在我尝试在会话2中插入新记录,会话“冻结”:
insert into d values (700);
当我在会话1中尝试执行相同的操作(使用另一个id字段)时,它会崩溃:
insert into d values (100); --> ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction in Session #1
insert into d values (700); --> Query OK, 1 row affected (4,08 sec) in Session #2
我怎样才能解决僵局?InnoDB状态为:
------------------------
LATEST DETECTED DEADLOCK
------------------------
2017-07-06 15:59:25 0x70000350d000
*** (1) TRANSACTION:
TRANSACTION 43567, ACTIVE 15 sec inserting
mysql tables in use 1, locked 1
LOCK WAIT 3 lock struct(s), heap size 1136, 2 row lock(s), undo log entries 1
MySQL thread id 4, OS thread handle 123145358217216, query id 89 localhost root update
insert into d values (700)
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 126 page no 4 n bits 72 index id of table `trx`.`d` trx id 43567 lock_mode X insert intention waiting
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
0: len 8; hex 73757072656d756d; asc supremum;;
*** (2) TRANSACTION:
TRANSACTION 43568, ACTIVE 7 sec inserting
mysql tables in use 1, locked 1
3 lock struct(s), heap size 1136, 2 row lock(s), undo log entries 1
MySQL thread id 3, OS thread handle 123145357938688, query id 90 localhost root update
insert into d values (100)
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 126 page no 4 n bits 72 index id of table `trx`.`d` trx id 43568 lock_mode X
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
0: len 8; hex 73757072656d756d; asc supremum;;
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 126 page no 4 n bits 72 index id of table `trx`.`d` trx id 43568 lock_mode X insert intention waiting
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
0: len 8; hex 73757072656d756d; asc supremum;;
*** WE ROLL BACK TRANSACTION (2)
最佳答案
我怀疑之所以会出现僵局,是因为innodb在处理“缺口”方面比较保守。请注意,100和700都在同一片未受影响的土地上。innodb不能(或者至少不能)处理“100”和“700”不同的事实。innodb想要标记单独的行,但是表中没有具有这些id的行。
事务2可能会超时(请参见innodb_lock_wait_timeout
)。当你第二次戳事务1时,2仍然需要一个锁,innodb拒绝了。
底线:与死锁一起生活。当它们发生时,从BEGIN
开始。你已经发现了另一个不必要的死锁发生的模糊情况。
此外,我怀疑修复此案例的代码会减慢大多数其他案例的速度,并导致一系列错误,这些错误需要几个版本才能发现和修复。
关于mysql - 在MySQL中插入意图锁的解决方案,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/44949940/