【发布时间】:2019-06-03 21:42:29
【问题描述】:
表:
create table properties
(
id int auto_increment primary key,
other_id int null
);
create index index_properties_on_other_id
on properties (other_id);
TX 1:
start transaction;
SET @last_id = 1;
delete from `properties` WHERE `properties`.`other_id` = @last_id;
INSERT INTO `properties` (`other_id`) VALUES (@last_id);
commit
TX 2:
start transaction;
SET @last_id = 2;
delete from `properties` WHERE `properties`.`other_id` = @last_id;
INSERT INTO `properties` (`other_id`) VALUES (@last_id);
commit
假设在运行事务之前表是空的。
我的应用程序有 2 个用例。有时last_id 已经被另一行使用,因此它会被优先索引;但有时它会由先前的插入查询在同一个事务中生成,在这种情况下我会遇到死锁。
我需要在删除语句之后运行这两个事务。当我在 tx1 上运行 insert 时,它等待获得锁,然后我在 tx2 上运行 insert,tx2 出现死锁并回滚。
mysql | LATEST DETECTED DEADLOCK
mysql | ------------------------
mysql | 2019-06-03 21:01:05 0x7f0ba4052700
mysql | *** (1) TRANSACTION:
mysql | TRANSACTION 320051, ACTIVE 12 sec inserting
mysql | mysql tables in use 1, locked 1
mysql | LOCK WAIT 3 lock struct(s), heap size 1136, 2 row lock(s), undo log entries 1
mysql | MySQL thread id 286, OS thread handle 139687839577856, query id 17804 172.18.0.1 root update
mysql | INSERT INTO `properties` (`other_id`) VALUES (@last_id)
mysql | *** (1) WAITING FOR THIS LOCK TO BE GRANTED:
mysql | RECORD LOCKS space id 1524 page no 4 n bits 72 index index_properties_on_other_id of table `properties` trx id 320051 lock_mode X insert intention waiting
mysql | Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
mysql | 0: len 8; hex 73757072656d756d; asc supremum;;
mysql |
mysql | *** (2) TRANSACTION:
mysql | TRANSACTION 320052, ACTIVE 8 sec inserting
mysql | mysql tables in use 1, locked 1
mysql | 3 lock struct(s), heap size 1136, 2 row lock(s), undo log entries 1
mysql | MySQL thread id 287, OS thread handle 139687973168896, query id 17814 172.18.0.1 root update
mysql | INSERT INTO `properties` (`other_id`) VALUES (@last_id)
mysql | *** (2) HOLDS THE LOCK(S):
mysql | RECORD LOCKS space id 1524 page no 4 n bits 72 index index_properties_on_other_id of table `properties` trx id 320052 lock_mode X
mysql | Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
mysql | 0: len 8; hex 73757072656d756d; asc supremum;;
mysql |
mysql | *** (2) WAITING FOR THIS LOCK TO BE GRANTED:
mysql | RECORD LOCKS space id 1524 page no 4 n bits 72 index index_properties_on_other_id of table `properties` trx id 320052 lock_mode X insert intention waiting
mysql | Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
mysql | 0: len 8; hex 73757072656d756d; asc supremum;;
mysql |
mysql | *** WE ROLL BACK TRANSACTION (2)
删除语句后的锁状态:
mysql | ---TRANSACTION 320066, ACTIVE 90 sec
mysql | 2 lock struct(s), heap size 1136, 1 row lock(s)
mysql | MySQL thread id 287, OS thread handle 139687973168896, query id 18076 172.18.0.1 root
mysql | TABLE LOCK table `properties` trx id 320066 lock mode IX
mysql | RECORD LOCKS space id 1524 page no 4 n bits 72 index index_properties_on_other_id of table `properties` trx id 320066 lock_mode X
mysql | Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
mysql | 0: len 8; hex 73757072656d756d; asc supremum;;
mysql |
mysql | ---TRANSACTION 320065, ACTIVE 95 sec
mysql | 2 lock struct(s), heap size 1136, 1 row lock(s)
mysql | MySQL thread id 286, OS thread handle 139687839577856, query id 18039 172.18.0.1 root
mysql | TABLE LOCK table `properties` trx id 320065 lock mode IX
mysql | RECORD LOCKS space id 1524 page no 4 n bits 72 index index_properties_on_other_id of table ``properties` trx id 320065 lock_mode X
mysql | Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
mysql | 0: len 8; hex 73757072656d756d; asc supremum;;
所以两个事务正在删除/插入不同的other_ids,我没想到它们会陷入僵局。我想了解为什么会发生这种情况。
【问题讨论】:
-
我想你可能想锁定相关的表。看到这个答案:stackoverflow.com/questions/40749730/…
-
我认为你永远不应该明确锁定表。将隔离级别更改为“READ COMMITED”可能会有所帮助。
标签: mysql database innodb deadlock