当前位置:网站首页>mysql insert 时出现Deadlock死锁场景分析
mysql insert 时出现Deadlock死锁场景分析
2022-06-29 08:22:00 【蜗牛的小牛】
案例一:
有一张表A,先更新,如果影响行数为0,则执行INSERT插入数据。很常见的场景,在生产上也跑了很久,没有出现什么问题。但是有一次在测试环境做压测时居然出现了死锁,Deadlock found when trying to get lock; try restarting transaction
因为对mysql锁不熟悉,为什么insert也会死锁,不是一般在update的时候会死锁吗? 很好奇,于是开始寻找原因…
mysql锁是跟数据库设置的隔离级别有关系的,不同的隔离级别,锁也各不相同,只要是为了解决类似脏读、幻读、可重复读的问题。
select @@tx_isolation; – 查看隔离级别
隔离级别是RR(可重复读),我们知道,在此隔离级别下,为了解决幻读的问题,会有存在间隙锁和Next-key lock(行锁 + 间隙锁),即在update、delete语句后会产生间隙锁和Next-key lock,如果在并发下,存在两个事务都事前执行了UPDATE语句(各自持有了gap lock),当INSERT时,要先在插入间隙上获取插入意向锁,由于插入数据的间隙存在冲突,所以会互相等待获取插入意向锁,即相互竞争,最终会导致一方死锁。
这也解释了为什么在测试环境出现死锁。
解决:
- 不采用事务,即无事务方式执行,但是如果出现异常则会出现数据不一致的情况。
- 调整事务隔离级别为read commit,RC级别不会产生gap lock
由于我们都知道事务的重要性,所以选择第二种方式,将隔离级别改为RC。我们在生产环境一般也就这个级别,所以也解释了为什么在生产没有出现这个问题。
事务隔离级别调整可以通过spring的声明式事务方式来实现,通过注解@Transactional
@Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
public void calculationEntry(List<CampaignFeedback> campaignFeedbackList, String groovyScript) {
//todo
}
再次压测,死锁问题不再出现。
案例二:
由于业务需要,经常对某张表做更新或者写入,又不想每次都先查询是否存在再插入,所以使用了mysql的replace into来实现。
replace into 语法是如果表中存在主键或者唯一索引,它会按这个维度去判断是否存在,如果存在则会先delete在insert,即它会分开两步来操作,不保证原子性。
开始使用后觉得还是很方便的,毕竟不用自己去多查询一次,mysql自动帮我们完成了。 但是到了压测环节,死锁竟然又出现了。。。。。。
因为有了前面的经验,所以这都不是问题,于是按之前的方式改了。在测试环境跑了几次都没问题,以为都是一样的问题导致,所以就上线了。
上线后,当我去验证这个功能的时候,尼玛。。。死锁问题再一次出现在我的眼前。
我很慌,为什么这次不行,难道我代码被覆盖了? 翻看git的提交记录并没有。。
于是我们去咨询了DBA,他说replace into 这个不建议使用,因为在大并发环境下,肯定会出现死锁。建议我们使用 insert into … values … on duplicate key update … 来替代
于是按DBA建议改了,再次上线后,不管怎么并发都不会出现死锁。
原因分析,如果使用replace into mysql会默认开启Gap lock和Next-key lock,所以即使加了事务配置也不起作用。
最后附上 insert into … on duplicate key update 介绍:
语法:
INSERT INTO tablename (field1,field2, field3, …) VALUES(value1, value2, value3, …) ON DUPLICATE KEY UPDATE field1=value1,field2=value2, field3=value3, …;
也可以使用以下方式(这种支持批量插入)
INSERT INTO TABLE (a,b,c) VALUES
(1,2,3),
(2,5,7),
(3,3,6),
(4,8,2)
ON DUPLICATE KEY UPDATE a=VALUES(a), b=VALUES(b),c=VALUES(c);
边栏推荐
- cokkie和session的区别
- 航芯开发板&调试器
- Is it really safe to open a stock account online? Find the answer
- Actual combat memoir starts from webshell to break through the border
- hostname -f与uname -n的返回值可能不同
- 抽象类、接口
- Tutorial on building open source Internet of things platform
- 晋升或汇报,你真的把事情讲清楚了吗?
- 2022第六季完美童模 清远赛区 海选赛圆满落幕
- Enrollment brochure for system integration project management engineer certification in July 2022
猜你喜欢

sql server 用 administrator 权限运行吗?还是以普通用户运行呢?

laravel 8 实现 订单表按月份水平分表

2022第六季完美童模 合肥赛区 决赛圆满落幕

Enrollment brochure for system integration project management engineer certification in July 2022

MQTT第二话 -- emqx高可用集群实现

2022第六季完美童模 清远赛区 海选赛圆满落幕

【最全】PS各个版本下载安装及小试牛刀教程(PhotoShop CS3 ~~ PhotoShop 2022)

各種級數(調和、幾何)總結

The return values of hostname -f and uname -n may be different

2022 Season 6 perfect children's model Haikou competition area trial successfully concluded
随机推荐
Let you know today that the passing rate of the PMP Exam is 97%, is it believable
开发小技巧-图片资源管理
Notes on key words in the original English work biography of jobs (VIII) [chapter six]
编程语言
Calculus Learning
uniapp微信小程序报错 TypeError: Cannot read property ‘call‘ of undefined
Cdga | what is the core of digital transformation in the transportation industry?
Speech signal processing - Fundamentals (I): basic acoustic knowledge
io流的总结
在 RedisTemplate 中使用 scan
Wallpaper applet source code double ended wechat Tiktok applet
工厂模式
MT-yolov6训练及测试
Tutorial on building open source Internet of things platform
NP3 格式化输出(一)
P4769-[noi2018] bubble sort [combinatorics, tree array]
How to gain profits from the operation of the points mall
324. 摆动排序 II / 剑指 Offer II 102. 加减的目标值
MySQL的分库分表策略及应用场景
Baodawei of the people's Chain: break down barriers and establish a global data governance sharing and application platform