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

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

背景

批量对一张表进行replace into操作,每个SQL操作1000条数据,最近有同事反馈使用并发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锁,导致死锁产生。

 

相关文章:

http://mysql.taobao.org/monthly/2015/03/01/

https://cloud.tencent.com/developer/article/1574074

目录
相关文章
|
6月前
|
缓存 数据库
并发修改同一记录时需要加锁
并发修改同一记录时需要加锁
执行ALTER TABLE语句时如何避免长时间阻塞并发查询
执行ALTER TABLE语句时如何避免长时间阻塞并发查询
180 0
|
NoSQL 关系型数据库 MySQL
MySQL 常见死锁场景 -- 并发Replace into导致死锁
### MySQL Replace into issue MySQL 并发 Replace into 引起死锁问题 在之前的文章 [#issue 68021 MySQL unique check 问题](https://zhuanlan.zhihu.com/p/503880736)中, 我们已经介绍了在 MySQL 里面, 由于唯一键的检查(unique check), 导致 MySQ
424 0
【并发技术13】条件阻塞Condition的应用(一)
【并发技术13】条件阻塞Condition的应用
|
6月前
|
监控 关系型数据库 MySQL
MySQL 并发 replace 导致的死锁
一 前言死锁其实是一个很有意思也很有挑战的技术问题,大概每个DBA和部分开发朋友都会在工作过程中遇见。关于死锁我会持续写一个系列的案例分析,希望能够对想了解死锁的朋友有所帮助。本文是源于生产过程中一个死锁案例。二 背景知识官方文档[1]中表述:"REPLACE is done like an INS...
180 0
|
6月前
|
监控 关系型数据库 MySQL
MySQL 并发insert 唯一键冲突导致的死锁
一 前言死锁其实是一个很有意思也很有挑战的技术问题,大概每个DBA和部分开发朋友都会在工作过程中遇见。关于死锁我会持续写一个系列的案例分析,希望能够对想了解死锁的朋友有所帮助。二 背景知识2.1 insert 锁机制在分析死锁案例之前,我们先学习一下背景知识 insert 语句的加锁策略。我们先来看...
982 0
|
6月前
|
SQL 监控 关系型数据库
MySQL 并发delete不存在记录申请gap锁导致死锁
一 前言死锁,其实是一个很有意思也很有挑战的技术问题,大概每个DBA都会在工作过程中遇见。关于死锁我会持续写一个系列的案例分析,希望能够对想了解死锁的朋友有所帮助。本文源于我们的生产案例:并发申请gap锁导致的死锁案例,与之前的 死锁案例一不同,本案例是因为RR模式下两个事务中的sql可以获取同一个...
185 0
并发锁(一):为什么要加锁
并发锁(一):为什么要加锁
162 0
并发锁(一):为什么要加锁
|
关系型数据库 MySQL
Mysql 查看死锁,解除死锁的方法
Mysql 查看死锁,解除死锁的方法
313 0