Table:
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
Assume table is empty prior to running transactions.
My application has 2 use cases. Sometimes last_id
would already be used by another row, hence it would be indexed prior; but sometimes it would be generated in same transaction by a previous insert query, and in that case I get a deadlock.
I need to run both transactions until after delete statement. And when I run insert on tx1, it waits to get a lock, then I run insert on tx2, tx2 gets a deadlock and rollsback.
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)
Status of locks after delete statements:
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;;
So two transactions are deleting/inserting different other_id
s, I wasn't expecting them to get into a deadlock. I want to learn why exactly this is happening.