MySQL优化--INSERT ON DUPLICATE UPDATE死锁
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死锁的更多相关文章
- Mysql中INSERT ... ON DUPLICATE KEY UPDATE的实践
转: Mysql中INSERT ... ON DUPLICATE KEY UPDATE的实践 阿里加多 0.1 2018.03.23 17:19* 字数 492 阅读 2613评论 2喜欢 1 一.前 ...
- sqlalchemy insert on duplicate update
sqlalchemy insert on duplicate update from sqlalchemy.dialects.mysql import insert insert_stmt = ins ...
- MySQL的INSERT ··· ON DUPLICATE KEY UPDATE使用的几种情况
在MySQL数据库中,如果在insert语句后面带上ON DUPLICATE KEY UPDATE 子句,而要插入的行与表中现有记录的惟一索引或主键中产生重复值,那么就会发生旧行的更新:如果插入的行数 ...
- SQLSERVER 中实现类似Mysql的 INSERT ON DUPLICATE KEY UPDATE
通过SQLServer创建索引时,有一个IGNORE_DUP_KEY的选项,可以类似实现. IGNORE_DUP_KEY = { ON | OFF } 指定对唯一聚集索引或唯一非聚集索引执行多行插入操 ...
- 死锁问题------------------------INSERT ... ON DUPLICATE KEY UPDATE*(转)
前言 我们在实际业务场景中,经常会有一个这样的需求,插入某条记录,如果已经存在了则更新它如果更新日期或者某些列上的累加操作等,我们肯定会想到使用INSERT ... ON DUPLICATE K ...
- INSERT ... ON DUPLICATE KEY UPDATE产生death lock死锁原理
前言 编辑 我们在实际业务场景中,经常会有一个这样的需求,插入某条记录,如果已经存在了则更新它如果更新日期或者某些列上的累加操作等,我们肯定会想到使用INSERT ... ON DUPLICATE K ...
- Mysql死锁如何排查:insert on duplicate死锁一次排查分析过程
前言 遇到Mysql死锁问题,我们应该怎么排查分析呢?之前线上出现一个insert on duplicate死锁问题,本文将基于这个死锁问题,分享排查分析过程,希望对大家有帮助. 死锁案发还原 表结构 ...
- mysql优化 ON DUPLICATE KEY UPDATE
场景:比如,有一张表,专门记录业务里的唯一数据记录,这张表里如果存在此唯一数据的记录就更新此行数据的某个字段,如果此唯一数据不存在,那么就添加一条最新数据. 一贯操作:如果不知道mysql有 ON D ...
- mysql 插入重复值 INSERT ... ON DUPLICATE KEY UPDATE
向数据库插入记录时,有时会有这种需求,当符合某种条件的数据存在时,去修改它,不存在时,则新增,也就是saveOrUpdate操作.这种控制可以放在业务层,也可以放在数据库层,大多数数据库都支持这种需求 ...
随机推荐
- Redis master/slave,sentinel,Cluster简单总结
现在互联网项目中大量使用了redis,本文著主要分析下redis 单点,master/slave,sentinel模式.cluster的一些特点. 一.单节点模式 单节点实例还是比较简单的,平时做个测 ...
- linux内存黑洞
1.问题 k8s集群中node节点的内存使用率居高不下,使用率达到90%多.通过以下命令可以发现此虚拟机分配的内存为15g,但是用户进程使用的内存总共为7个多g,并且slab和pageTables使用 ...
- leetcode8:字符串转整数 (atoi)
实现 atoi,将字符串转为整数. 在找到第一个非空字符之前,需要移除掉字符串中的空格字符.如果第一个非空字符是正号或负号,选取该符号,并将其与后面尽可能多的连续的数字组合起来,这部分字符即为整数的值 ...
- day 2:计算机的基础知识,编程语言分类
本节内容 1,计算机的容量 2,编程语言介绍1,计算机的容量 1位 = 1bit 8bit = 1byte = 1字节 1024bytes = 1k bytes = 1KB 1024个 1024KB ...
- try_files
try_files $uri $uri/ /index.php$is_args$args 假设你防问 https://demo.com/demo 1.$uri:查找/demo文件 2.$ui/:查找/ ...
- dubbo服务达成jar包
<build> <finalName>dubbo-provider</finalName> <!-- jar包名,一般设置为提供者服务名 --> < ...
- zabbix监控配置与邮件告警
添加主机与主机组 进入web页面,在 配置-主机群组,创建主机群组 在 配置-主机,新建主机 在可见的名称中建议填写为类似 主机类型-主机名-IP或域名 的格式,如Web-Hyrule001-192. ...
- Itreatot接口实现类中modCount的作用
modCount只有在本数据结构对应迭代器中才使用,以HashMap为例: private abstract class HashIterator implements Iterator { Entr ...
- AtCoder Regular Contest 090
C - Candies 链接:https://arc090.contest.atcoder.jp/tasks/arc090_a 题意:从左上角走到右下角,只能向右和向下走,问能最多能拿多少糖果. 思路 ...
- c#串口测试
软件和代码网盘下载 https://pan.baidu.com/s/1dFrE1pv#list/path=%2F SerialPort 类 https://msdn.microsoft.com/zh- ...