首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >​insert on duplicate key死锁问题分析

​insert on duplicate key死锁问题分析

作者头像
AsiaYe
发布于 2020-01-13 11:16:38
发布于 2020-01-13 11:16:38
2.4K0
举报
文章被收录于专栏:DBA随笔DBA随笔

//

insert on duplicate key死锁问题分析

//

开始今天的文章之前,先说明下昨天文章中的一个错误,昨天文章最后说replace into带来的死锁问题可以使用insert into duplicate key update的方法来解决,今天实际测试的时候,还是遇到了一些问题,改方法并没有完全解决死锁的问题,来看测试的结果。

首先,我们新建一个test表,其中包含3列,a,b,c,其中a是主键,b是唯一索引,c是普通列,往test表中插入一条记录,该记录如下:(2020,5,5),然后在3个会话中执行下面的语句:

死锁信息对应的命令行输出如下:

代码语言:javascript
复制
mysql:yeyztest 22:14:18>>begin;
Query OK, 0 rows affected (0.00 sec)
mysql:yeyztest 22:14:20>>replace into test_replace values (2024,5,5);
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
mysql:yeyztest 22:14:31>>replace into test_replace values (2024,5,5);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

这是在使用replace的方法进行插入的时候遇到的问题。当我们将3个session中的replace的方法全部换成insert into ... on duplicate key的时候,该问题没有得到解决,还是报一样的错误,如下:

代码语言:javascript
复制
mysql :yeyztest 22:15:44>>begin;
Query OK, 0 rows affected (0.00 sec)

mysql :yeyztest 22:20:16>>insert into test_replace values (2025,5,5) on duplicate key update id=2024;
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

查询了MySQL在insert的时候的加锁情况,官网上的介绍如下:

https://dev.mysql.com/doc/refman/5.7/en/innodb-locks-set.html

详读官方文档上的这个文章,相信可以解决你的疑问。

该网址上面的例子,几乎完整的复现了上述死锁的情况,就是说,加入有两条并发的insert操作要对同一条记录加共享锁,而此时这条记录又被其他事务加上了排它锁,当排它锁的事务回滚或者提交之后,两个并发的insert操作是会发生死锁的,原因是由于这两条并发的insert操作,都对这条记录加上了共享锁,所以都无法获取该条记录的排它锁,除非一条insert语句回滚。

最后给出一张锁的兼容性的表供大家参考:

有帮助的话还希望点下再看哈

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-01-08,如有侵权请联系 cloudcommunity@tencent.com 删除
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档