mysql死锁语句_MySQL:死锁一例

本文通过一个具体的案例分析了MySQL中的死锁问题,详细解释了死锁产生的原因和过程。作者使用了一个特别的日志记录版本,展示了如何通过日志分析死锁发生的详细步骤,帮助读者理解数据库加锁机制和避免死锁的方法。
摘要由CSDN通过智能技术生成

欢迎关注我的《深入理解MySQL主从原理 32讲 》,如下:

![image.png](https://upload-images.jianshu.io/upload_images/7398834-0ffa3bdc078cddf4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

如果图片不能显示可查看下面链接:

https://www.jianshu.com/p/d636215d767f

###一、问题由来

这是我同事问我的一个问题,在网上看到了如下案例,本案例RC RR都可以出现,其实这个死锁原因也不叫简单,我们来具体看看:

#####构造数据

```

CREATE database deadlock_test;

use deadlock_test;

CREATE TABLE `push_token` (

`id` bigint(20) NOT NULL AUTO_INCREMENT,

`token` varchar(128) NOT NULL COMMENT 'push token',

`app_id` varchar(128) DEFAULT NULL COMMENT 'appid',

`deleted` tinyint(1) NOT NULL COMMENT '是否已删除 0:否 1:是',

PRIMARY KEY (`id`),

UNIQUE KEY `uk_token_appid` (`token`,`app_id`)

) ENGINE=InnoDB AUTO_INCREMENT=3384 DEFAULT CHARSET=utf8 COMMENT='pushtoken表';

insert into push_token (id, token, app_id, deleted) values(1,"token1",1,0);

```

#####操作数据

|s1(TRX_ID367661)|s2(TRX_ID367662)|s3(TRX_ID367663)|

|-|-|-|

|begin; UPDATE push_token SET deleted = 1 WHERE token = 'token1' AND app_id = '1';|||

||begin; DELETE FROM push_token WHERE id IN (1);||

|||begin; UPDATE push_token SET deleted = 1 WHERE token = 'token1' AND app_id = '1';|

|commit;|||

|Query OK, 0 rows affected (0.00 sec)|Query OK, 1 row affected (17.32 sec)|ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction|

###二、分析方法

我使用的分析方法是把整个加锁的日志打印出来,当然需要用到我自己做了输出修改的一个版本,如下:

https://github.com/gaopengcarl/percona-server-locks-detail-5.7.22

这个版本我打开了的日志记录参数如下:

```

mysql> show variables like '%gaopeng%';

+--------------------------------+-------+

| Variable_name | Value |

+--------------------------------+-------+

| gaopeng_mdl_detail | OFF |

| innodb_gaopeng_row_lock_detail | ON |

+--------------------------------+-------+

2 rows in set (0.01 sec)

```

这样大部分的innodb加锁记录都会记录到errlog日志了。好了下面我详细分析一下日志:

###三、分析过程

初始化的情况整个表只有1条记录,本表包含一个主键和一个唯一键。

- ####s1(TRX_ID367661) 执行语句

```

begin;

UPDATE push_token SET deleted = 1 WHERE token = 'token1' AND app_id = '1';

```

日志输出:

```

2019-08-18T19:10:05.117317+08:00 6 [Note] InnoDB: TRX ID:(367661) table:deadlock_test/push_token index:uk_token_appid space_id: 449 page_id:4 heap_no:2 row lock mode:LOCK_X|LOCK_NOT_GAP|

PHYSICAL RECORD: n_fields 3; compact format; info bits 0

0: len 6; hex 746f6b656e31; asc token1;;

1: len 1; hex 31; asc 1;;

2: len 8; hex 8000000000000001; asc ;;

2019-08-18T19:10:05.117714+08:00 6 [Note] InnoDB: TRX ID:(367661) table:deadlock_test/push_token index:PRIMARY space_id: 449 page_id:3 heap_no:2 row lock mode:LOCK_X|LOCK_NOT_GAP|

PHYSICAL RECORD: n_fields 6; compact format; info bits 0

0: len 8; hex 8000000000000001; asc ;;

1: len 6; hex 000000059c2c; asc ,;;

2: len 7; hex bf000000420110; asc B ;;

3: len 6; hex 746f6b656e31; asc token1;;

4: len 1; hex 31; asc 1;;

5: len 1; hex 80; asc ;;

```

我们看到主键和唯一键都加锁了如下图:

![](http://img.blog.itpub.net/blog/2019/07/22/3ca7923c72d7a031.png?x-oss-process=style/bb)

- ####s2(TRX_ID367662) 执行语句

```

begin;DELETE FROM push_token WHERE id IN (1);

````

日志输出:

```

2019-08-18T19:10:22.751467+08:00 9 [Note] InnoDB: TRX ID:(367662) table:deadlock_test/push_token index:PRIMARY space_id: 449 page_id:3 heap_no:2 row lock mode:LOCK_X|LOCK_NOT_GAP|

PHYSICAL RECORD: n_fields 6; compact format; info bits 0

0: len 8; hex 8000000000000001; asc ;;

1: len 6; hex 000000059c2d; asc -;;

2: len 7; hex 400000002a1dc8; asc @ * ;;

3: len 6; hex 746f6b656e31; asc token1;;

4: len 1; hex 31; asc 1;;

5: len 1; hex 81; asc ;;

2019-08-18T19:10:22.752753+08:00 9 [Note] InnoDB: Trx(367662) is blocked!!!!!

```

这个时候S2需要获取主键上的锁,因此被堵塞了如下图:

![](http://img.blog.itpub.net/blog/2019/07/22/ed4a28ad9b644cf0.png?x-oss-process=style/bb)

- ####s3(TRX_ID367663) 执行语句

```

begin; UPDATE push_token SET deleted = 1 WHERE token = 'token1' AND app_id = '1';

````

日志输出:

```

019-08-18T19:10:30.822111+08:00 8 [Note] InnoDB: TRX ID:(367663) table:deadlock_test/push_token index:uk_token_appid space_id: 449 page_id:4 heap_no:2 row lock mode:LOCK_X|LOCK_NOT_GAP|

PHYSICAL RECORD: n_fields 3; compact format; info bits 0

0: len 6; hex 746f6b656e31; asc token1;;

1: len 1; hex 31; asc 1;;

2: len 8; hex 8000000000000001; asc ;;

2019-08-18T19:10:30.918248+08:00 8 [Note] InnoDB: Trx(367663) is blocked!!!!!

```

这个时候S3需要获取唯一键上的锁,因此被堵塞了如下图:

![](http://img.blog.itpub.net/blog/2019/07/22/1d3aadc33999ca42.png?x-oss-process=style/bb)

- ####s1(TRX_ID367661) 执行语句

这一步完成后死锁出现。

```

commit;

```

日志输出如下:

```

367663和367662各自获取需要的锁

2019-08-18T19:10:36.566733+08:00 8 [Note] InnoDB: TRX ID:(367663) table:deadlock_test/push_token index:uk_token_appid space_id: 449 page_id:4 heap_no:2 row lock mode:LOCK_X|LOCK_NOT_GAP|

PHYSICAL RECORD: n_fields 3; compact format; info bits 0

0: len 6; hex 746f6b656e31; asc token1;;

1: len 1; hex 31; asc 1;;

2: len 8; hex 8000000000000001; asc ;;

2019-08-18T19:10:36.568711+08:00 9 [Note] InnoDB: TRX ID:(367662) table:deadlock_test/push_token index:PRIMARY space_id: 449 page_id:3 heap_no:2 row lock mode:LOCK_X|LOCK_NOT_GAP|

PHYSICAL RECORD: n_fields 6; compact format; info bits 0

0: len 8; hex 8000000000000001; asc ;;

1: len 6; hex 000000059c2d; asc -;;

2: len 7; hex 400000002a1dc8; asc @ * ;;

3: len 6; hex 746f6b656e31; asc token1;;

4: len 1; hex 31; asc 1;;

5: len 1; hex 81; asc ;;

367663获取主键锁堵塞、367662获取唯一键锁堵塞,死锁形成

2019-08-18T19:10:36.570313+08:00 8 [Note] InnoDB: TRX ID:(367663) table:deadlock_test/push_token index:PRIMARY space_id: 449 page_id:3 heap_no:2 row lock mode:LOCK_X|LOCK_NOT_GAP|

PHYSICAL RECORD: n_fields 6; compact format; info bits 0

0: len 8; hex 8000000000000001; asc ;;

1: len 6; hex 000000059c2d; asc -;;

2: len 7; hex 400000002a1dc8; asc @ * ;;

3: len 6; hex 746f6b656e31; asc token1;;

4: len 1; hex 31; asc 1;;

5: len 1; hex 81; asc ;;

2019-08-18T19:10:36.571199+08:00 8 [Note] InnoDB: Trx(367663) is blocked!!!!!

2019-08-18T19:10:36.572481+08:00 9 [Note] InnoDB: TRX ID:(367662) table:deadlock_test/push_token index:uk_token_appid space_id: 449 page_id:4 heap_no:2 row lock mode:LOCK_X|LOCK_NOT_GAP|

PHYSICAL RECORD: n_fields 3; compact format; info bits 0

0: len 6; hex 746f6b656e31; asc token1;;

1: len 1; hex 31; asc 1;;

2: len 8; hex 8000000000000001; asc ;;

2019-08-18T19:10:36.573073+08:00 9 [Note] InnoDB: Transactions deadlock detected, dumping detailed information.

```

这个时候我们看到s2和s3先是获取了各自需要的锁,s3获取主键锁堵塞,s2获取唯一键锁堵塞,死锁出现。如下图:

![](http://img.blog.itpub.net/blog/2019/07/22/9ecf8aa1cec15870.png?x-oss-process=style/bb)

好了我们看到了死锁就这样出现。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值