INSERT ON DUPLICATE UPDATE与死锁
在MySQL中提供两种插入更新的方式:REPLACE INTO和INSERT ON DUPLICATE UPDATE,简化了“存在则更新,不存在则插入”的实现逻辑,但这两种方式在MySQL内部都被拆分为多个操作步骤且引入GAP锁来保证数据完整性,因此在高并发情况下极易产生死锁。
##==================================================##
在MySQL中INSERT ON DUPLICATE UPDATE的加锁流程:
1. Innodb存储引擎尝试INSER INTO操作
2. 如果插入成功,则忽略DUPLICATE UPDATE部分并返回
3. 如果插入失败,则表明有相同记录存在,对该记录加共享锁(S)
4. 执行DUPLICATE UPDATE语句,对记录加X锁,然后更新记录。

##==================================================##
对于INSERT ON DUPLICATE UPDATE操作,当两个会话S1和S2使用INSERT ON DUPLICATE UPDATE语句操作相同数据且表中存在相同键值记录时,触发死锁场景为:
1. 由于表中已存在重复键值的记录,导致会话先后尝试INSER失败
2. 会话S1进入步骤3尝试获取记录的S锁,该记录未被其他会话加锁,获取S锁成功。
3. 会话S2进入步骤3尝试获取记录的S锁,该记录上被加持S锁,但由于S锁与S锁兼容,获取S锁成功
4. 会话S1进入步骤4尝试获取记录的X锁,由于会话S2对该记录持有S锁,S锁与X锁不兼容,获取X锁失败,会话S1被阻塞
5. 会话S2进入步骤4尝试获取记录的X锁,由于会话S1对该记录持有S锁,S锁与X锁不兼容,获取X锁失败,会话S2被阻塞
6. 会话S2被阻塞后进入死锁检查环节,发现阻塞S1->S2和S2->S1形成死锁环路,触发死锁机制强制回滚S1或S2事务。

##==================================================##
在MySQL默认隔离级别REPEATABLE READ下,为避免出现"幻读"发生,防止其他会话插入相同键值的记录。
对于普通INSERT操作加锁如下:
1. 对于非唯一索引,需要对新记录加排他锁(X),另外对新记录和新记录的相邻记录的区间加gap锁。
2. 对于唯一索引,仅需要对新记录加排他锁(X),唯一索引特性保证其他会话无法插入相同键值。

对于INSERT ON DUPLICATE UPDATE操作,当表中未存在重复键值记录时,加锁特点如下:
1. 对于唯一索引和非唯一索引,都需要对新记录加排他锁(X),另外对新记录和新记录的相邻记录的区间加gap锁。

##==================================================##
准备测试数据:
CREATE TABLE `tb2002` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`c1` varchar(20) DEFAULT NULL,
`c2` varchar(20) DEFAULT NULL,
`c3` int(11) DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_c1` (`c1`,`c2`)
) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8;

insert into tb2002(c1,c2) values('a','1');
insert into tb2002(c1,c2) values('f','1');

开始测试:
会话1执行:
insert into tb2002(c1,c2) values('d','2') ON DUPLICATE KEY UPDATE c3=c3+1;
执行成功

会话2执行:
insert into tb2002(c1,c2) values('c','1') ON DUPLICATE KEY UPDATE c3=c3+1;
执行被阻塞,等待X+GAP锁,GAP锁的行记录目标是('f','1')

会话1执行:
insert into tb2002(c1,c2) values('d','1') ON DUPLICATE KEY UPDATE c3=c3+1;
触发死锁,会话2被回滚,会话1执行成功

##==================================================##
通过上面两个死锁案例,我们强烈建议在生产环境中尽量避免使用REPLACE INTO和INSERT INTO ON DUPLICATE UPDATE语句,改用普通INSERT操作,并对INSER操作部分代码加入异常加查,当INSERT失败时改为UPDATE操作。

MySQL优化--INSERT ON DUPLICATE UPDATE死锁的更多相关文章

  1. Mysql中INSERT ... ON DUPLICATE KEY UPDATE的实践

    转: Mysql中INSERT ... ON DUPLICATE KEY UPDATE的实践 阿里加多 0.1 2018.03.23 17:19* 字数 492 阅读 2613评论 2喜欢 1 一.前 ...

  2. sqlalchemy insert on duplicate update

    sqlalchemy insert on duplicate update from sqlalchemy.dialects.mysql import insert insert_stmt = ins ...

  3. MySQL的INSERT ··· ON DUPLICATE KEY UPDATE使用的几种情况

    在MySQL数据库中,如果在insert语句后面带上ON DUPLICATE KEY UPDATE 子句,而要插入的行与表中现有记录的惟一索引或主键中产生重复值,那么就会发生旧行的更新:如果插入的行数 ...

  4. SQLSERVER 中实现类似Mysql的 INSERT ON DUPLICATE KEY UPDATE

    通过SQLServer创建索引时,有一个IGNORE_DUP_KEY的选项,可以类似实现. IGNORE_DUP_KEY = { ON | OFF } 指定对唯一聚集索引或唯一非聚集索引执行多行插入操 ...

  5. 死锁问题------------------------INSERT ... ON DUPLICATE KEY UPDATE*(转)

    前言    我们在实际业务场景中,经常会有一个这样的需求,插入某条记录,如果已经存在了则更新它如果更新日期或者某些列上的累加操作等,我们肯定会想到使用INSERT ... ON DUPLICATE K ...

  6. INSERT ... ON DUPLICATE KEY UPDATE产生death lock死锁原理

    前言 编辑 我们在实际业务场景中,经常会有一个这样的需求,插入某条记录,如果已经存在了则更新它如果更新日期或者某些列上的累加操作等,我们肯定会想到使用INSERT ... ON DUPLICATE K ...

  7. Mysql死锁如何排查:insert on duplicate死锁一次排查分析过程

    前言 遇到Mysql死锁问题,我们应该怎么排查分析呢?之前线上出现一个insert on duplicate死锁问题,本文将基于这个死锁问题,分享排查分析过程,希望对大家有帮助. 死锁案发还原 表结构 ...

  8. mysql优化 ON DUPLICATE KEY UPDATE

    场景:比如,有一张表,专门记录业务里的唯一数据记录,这张表里如果存在此唯一数据的记录就更新此行数据的某个字段,如果此唯一数据不存在,那么就添加一条最新数据. 一贯操作:如果不知道mysql有 ON D ...

  9. mysql 插入重复值 INSERT ... ON DUPLICATE KEY UPDATE

    向数据库插入记录时,有时会有这种需求,当符合某种条件的数据存在时,去修改它,不存在时,则新增,也就是saveOrUpdate操作.这种控制可以放在业务层,也可以放在数据库层,大多数数据库都支持这种需求 ...

随机推荐

  1. Django 的认识,面试题

    Django 的认识,面试题 1. 对Django的认识? #1.Django是走大而全的方向,它最出名的是其全自动化的管理后台:只需要使用起ORM,做简单的对象定义,它就能自动生成数据库结构.以及全 ...

  2. mysql启动服务

    mysql.server start 启动mysql服务mysql.server stop 停止mysql服务 mysql密码:123456Az_

  3. python json.dumps()函数输出json格式,使用ensure_ascii参数对中文输入的支持

    在python使用过程中,输入中文,不能正常的输出,可以使用ensure_ascii参数来解决不能输入中文的问题 代码块: import json friends={"name": ...

  4. 常用的三种json软件的使用

    从几个角度比较三种软件 1. json操作 2 反解 3 性能 易用性还没有列出. 可以根据个人喜好进行取舍. package json; import com.alibaba.fastjson.JS ...

  5. 天然气管道Gaz[POI2007]

    --BZOJ1034 题目描述 Mary试图控制成都的天然气市场.专家已经标示出了最好的天然气井和中转站在成都的地图.现在需要将中转 站和天然气井连接起来.每个中转站必须被连接到正好一个钻油井,反之亦 ...

  6. MySQL ERROR 1064(42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near

    通常出现该错误的原因是使用了 MySQL 的保留字 解决方法是对使用的保留字使用反引号  (Tab键上面)

  7. ListView点击事件失效(item里面有button按钮控件)解决方法

    ListView点击事件失效解决方法: 一般出现这个情况,就是你的item里面有按钮的点击事件,你的item里面有button控件,button控件是抢占焦点的,只要在你的item布局里面这样子写就可 ...

  8. left join中where与on的区别

    举例进行说明,我们现在有两个表,即商品表(products)与sales_detail(销售记录表).我们主要是通过这两个表来对MySQL关联left join 条件on与where 条件的不同之处进 ...

  9. Mysql常用命令 详细整理版

    Mysql常用命令 show databases; 显示数据库 create database name; 创建数据库 use databasename; 选择数据库 drop database na ...

  10. 2018上IEC计算机高级语言(C)作业 第3次作业_说明

    一.博客作业内容 2018上IEC计算机高级语言(C)作业 第3次作业 二.评分规则说明 1.程序调试题,要描述出调试所遇到问题及修改内容,并表述清楚程序功能.流程图不规范的会减1-2分: 2.知识点 ...