首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >并发replace操作导致的死锁问题

并发replace操作导致的死锁问题

作者头像
AsiaYe
发布2020-01-15 15:07:28
4.7K0
发布2020-01-15 15:07:28
举报
文章被收录于专栏:DBA随笔DBA随笔

//

并发replace操作导致的死锁问题

//

今天上班的时候,遇到了一个问题,有业务同学反应使用并发replace操作的时候,遇到了死锁的问题。针对这个问题,我看了看表的结构,发现表中有一个主键,一个唯一索引,然后用replace的操作去对表中的记录进行插入,如果存在相同的唯一索引,那么就更新这条记录。

开始分析这个问题之前,我们首先对replace into这个语法做个简单了解,replace into的语法是当我们不确定即将插入的记录是否存在唯一性冲突时,可以通过Replace into的方式让MySQL自动处理:当存在冲突时,会把旧记录替换成新的记录。

假设我们有表test

create table test (

a int auto_increment primary key,

b int,

c int,

unique key (b)

);

那么一个replace into的语句执行过程可能如下:

上面的图中,有几点需要解释:

1、当我们判断唯一索引的记录是否唯一时,需要对该条记录加上X锁,也就是第2步下面的判断时,需要加X锁

2、第5步检测该唯一索引,并对索引上的记录加X锁,在这个过程中,对于唯一索引对应的聚集索引记录,也需要加X锁。

3、第5步后面的条件判断的内容如下:

  • 如果发生uk冲突的索引是最后一个唯一索引、没有外键引用、且不存在delete trigger时,使用UPDATE ROW的方式来解决冲突;
  • 否则,使用DELETE ROW + INSERT ROW的方式解决冲突。

详见:淘宝数据库月报

4、第6步和第7步,本质上是在更新唯一索引列上的记录。

5、第8步需要更新聚集索引列上的记录,该过程中,如果插入位置的下一条记录上存在记录锁,那么在插入时,当前session需要对其加插入意向锁,具体类型为LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION。这也是导致死锁的关键点之一

死锁成因分析:

1、假设我们有两个会话,也就是session

2、session1执行到第6或者第7步,准备更新唯一索引和聚集索引记录,更新前,需要持有该唯一索引和聚集索引的记录锁,假设该记录是unique key=2020的一条记录

3、此时session2发现了唯一索引冲突,也就是图中第2步下面的"判断重复记录"过程中,出现了索引冲突,也在记录上加X锁,假设该记录是unique key=2021的一条记录

4、session 1 在标记删除记录后,尝试插入新的unique key记录,发现预插入记录2020的下一条记录2021上有锁请求,因此尝试加插入意向X锁,导致死锁产生。

如何解决?

鉴于该业务表只有一个主键字段和一个唯一索引字段,在该情况下,我们可以使用insert into ... on duplicate key update的方法去代替replace的方法。

时间原因,今天的内容就到这里吧,不然超时了。。。

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

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-01-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 DBA随笔 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 MySQL
腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档