mysql insert into select 死锁_mysql insert导致死锁

两个insert语句发生死锁的案例。

一. 准备数据

CREATE TABLE `t1` (

`a` int(11) NOT NULL,

PRIMARY KEY (`a`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

insert into t1 values(1);

mysql> insert into t1 values(1);

Query OK, 1 row affected (0.20 sec)

mysql> select * from t1;

+---+

| a |

+---+

| 1 |

+---+

1 row in set (0.00 sec)

二. 发起如下事务

会话1

会话2

会话3

begin;

delete from t1 where a=1;

begin;

insert into t1 select 1;

begin;

insert into t1 select 1;

Commit

ERROR 1213 (40001): Deadlock found when   trying to get lock; try restarting transaction

简单理解下,删除数据的会话持有X锁,导致两条insert语句需要等待,这没问题,

但是为什么删除提交后,两个竞争关系出现了死锁。

show engine innodb status部分结果:

------------------------

LATEST DETECTED DEADLOCK

------------------------

2020-05-17 13:50:24 0x7f660c3f0700

*** (1) TRANSACTION:

TRANSACTION 4377, ACTIVE 13 sec inserting

mysql tables in use 1, locked 1

LOCK WAIT 3 lock struct(s), heap size 1136, 2 row lock(s)

MySQL thread id 3, OS thread handle 140076399294208, query id 59 localhost root executing

insert into t1 select 1

*** (1) WAITING FOR THIS LOCK TO BE GRANTED:

RECORD LOCKS space id 99 page no 3 n bits 72 index PRIMARY of table `ming`.`t1` trx id 4377 lock_mode X locks rec but not gap waiting

Record lock, heap no 2 PHYSICAL RECORD: n_fields 3; compact format; info bits 32

0: len 4; hex 80000001; asc     ;;

1: len 6; hex 000000001114; asc       ;;

2: len 7; hex 3400000144129f; asc 4   D  ;;

*** (2) TRANSACTION:

TRANSACTION 4378, ACTIVE 10 sec inserting, thread declared inside InnoDB 1

mysql tables in use 1, locked 1

3 lock struct(s), heap size 1136, 2 row lock(s)

MySQL thread id 4, OS thread handle 140076268848896, query id 61 localhost root executing

insert into t1 select 1

*** (2) HOLDS THE LOCK(S):

RECORD LOCKS space id 99 page no 3 n bits 72 index PRIMARY of table `ming`.`t1` trx id 4378 lock mode S

Record lock, heap no 2 PHYSICAL RECORD: n_fields 3; compact format; info bits 32

0: len 4; hex 80000001; asc     ;;

1: len 6; hex 000000001114; asc       ;;

2: len 7; hex 3400000144129f; asc 4   D  ;;

*** (2) WAITING FOR THIS LOCK TO BE GRANTED:

RECORD LOCKS space id 99 page no 3 n bits 72 index PRIMARY of table `ming`.`t1` trx id 4378 lock_mode X locks rec but not gap waiting

Record lock, heap no 2 PHYSICAL RECORD: n_fields 3; compact format; info bits 32

0: len 4; hex 80000001; asc     ;;

1: len 6; hex 000000001114; asc       ;;

2: len 7; hex 3400000144129f; asc 4   D  ;;

*** WE ROLL BACK TRANSACTION (2)

可以看到会话2正在等待一个X行锁,会话3也在等待X行锁,但是同时持有一个S锁。

这个S锁是怎么来的呢?

当进行唯一性冲突检测时,需要先加一个 S 锁。

那么整个过程就是如下所示

会话1

会话2

会话3

begin;

delete from t1 where a=1;

持有a=1就的X行锁

begin;

insert into t1 select 1;

为了判断唯一性,请求a=1的next-key   lock S锁被阻塞,等待

begin;

insert into t1 select 1;

为了判断唯一性,请求a=1的next-key   lock S锁被阻塞,等待

Commit

释放a=1上的锁

拿到a=1的next-key lock   S锁,继续尝试拿a=1的X 行锁,但是被会话3的S锁阻塞

拿到a=1的next-key lock   S锁,继续尝试拿a=1的X 行锁,尝试拿到a=1的X 行锁,但是被会话2的S锁阻塞。

触发死锁

ERROR 1213 (40001): Deadlock found when   trying to get lock; try restarting transaction

你可能感兴趣的:(mysql,insert,into,select,死锁)