临键锁引发的死锁

简介: 【8月更文挑战第4天】

先说一个最简单的锁优化方案,MySQL的锁是依赖索引机制来实现的,如果查询没有使用索引,就会使用表锁,那么显然最简单的方案就是给这种查询创建一个索引,避免使用表锁。关键词是缺索引

早期发现我们的业务有一个神奇的性能问题,就是响应时间偶尔会突然延长,后来经过排查,确认响应时间是因为数据库查询变慢引起的。但是那些变长的查询,SQL完全没有问题,而且用EXPLAIN去分析,都很正常,也走了索引。
直到后面我们去排查业务代码的提交记录,才发现新加的功能会执行一个SQL,但是这个SQL本身不会命中任何索引,于是数据库就会使用表锁,偏偏这个SQL本身没有命中索引,又很慢,导致表锁一直得不到释放。结果其他正常的SQL反而被他拖累了。最终我们重新优化了这个使用表锁的SQL,让它走了一个索引,就解决了这个问题。

这个方案还是比较简单,还有两个稍微复杂的方案:

在一个业务中,有一个场景是先从数据库中查询数据并锁住。如果这个数据不存在,那么就需要执行一段逻辑,计算出一个数据,然后插入。如果已经有数据了,就把原始数据取出来,再利用这个数据执行一段逻辑,计算出一个结果,执行更新。
在这里插入图片描述
因为两端运算逻辑不同,所以不能简单地使用INSERT ON DUPLICATE的语句来取代。

以没有数据的逻辑来看,在计算之后插入新数据,伪代码如下:

BEGIN;
SELECT * FROM biz WHERE id = ? FOR UPDATE
// 中间有很多业务操作
INSERT INTO biz(id, data) VALUE(?, ?);
COMMIT;

事实上,这个地方会引起死锁。
假如现在数据库中ID最大的值是78,那么如果两个业务进来,同时执行这个逻辑,一个准备插入id=79的数据,一个准备插入id=80的数据,执行时序如下图

[40001][1213] Deadlock found when trying to get lock; try restarting transaction

造成死锁的原因是:在线程1执行SELECT FOR UPDATE的时候,因为id是79的数据不存在,所以数据库会产生一个(78,supremum]的临键锁;类似的,线程2也会产生一个(78,supremum]的临键锁。当线程1想要执行插入的时候,他想要获得79的行锁;当线程2想要执行插入的时候,它想要获得id=80的行锁,这个时候就会出现死锁,因为线程1和线程2同时还在等着对方释放掉持有的间隙锁。

目录
相关文章
|
Web App开发 人工智能 前端开发
【Web API系列】使用getDisplayMedia来实现录屏功能
【Web API系列】使用getDisplayMedia来实现录屏功能
1093 0
|
编译器 开发工具 C++
Qt5.6.3+VS2013环境搭建教程(最后支持XP系统的Qt版本)
Qt5.6.3+VS2013环境搭建教程(最后支持XP系统的Qt版本)
2781 0
Qt5.6.3+VS2013环境搭建教程(最后支持XP系统的Qt版本)
|
监控 Cloud Native 容器
基于阿里云容器服务监控 Kubernetes集群GPU指标
### 简介 当您在阿里云容器服务中使用GPU ECS主机构建Kubernetes集群进行AI训练时,经常需要知道每个Pod使用的GPU的使用情况,比如每块显存使用情况、GPU利用率,GPU卡温度等监控信息,本文介绍如何快速在阿里云上构建基于Prometheus + Grafana的GPU监控方案。
17586 0
|
存储 自然语言处理 算法
ES高频面试问题:一张图带你读懂 Elasticsearch 中“正排索引(正向索引)”和“倒排索引(反向索引)”区别
ES高频面试问题:一张图带你读懂 Elasticsearch 中“正排索引(正向索引)”和“倒排索引(反向索引)”区别
ES高频面试问题:一张图带你读懂 Elasticsearch 中“正排索引(正向索引)”和“倒排索引(反向索引)”区别
|
消息中间件 Java Kafka
在Java中实现分布式事务的常用框架和方法
总之,选择合适的分布式事务框架和方法需要综合考虑业务需求、性能、复杂度等因素。不同的框架和方法都有其特点和适用场景,需要根据具体情况进行评估和选择。同时,随着技术的不断发展,分布式事务的解决方案也在不断更新和完善,以更好地满足业务的需求。你还可以进一步深入研究和了解这些框架和方法,以便在实际应用中更好地实现分布式事务管理。
1429 161
|
人工智能 JSON 边缘计算
从零开始学MCP(1)| MCP 协议核心原理解析
MCP 协议统一 AI 工具调用标准,解决碎片化、高耦合与上下文丢失问题,采用 Client/Server 架构,支持上下文传递与 SSE 流式响应,提升工具调用效率与灵活性。
|
JavaScript 程序员 iOS开发
对比lingma、cursor辅助配置本地开发环境的能力
本文通过一个简单的环境配置的例子,展示lingma, cursor在辅助编程方面的解题思路、生成能力的差异。
736 5
|
安全 Java API
【Java性能优化】Map.merge()方法:告别繁琐判空,3行代码搞定统计累加!
在日常开发中,我们经常需要对Map中的值进行累加统计。}else{代码冗长,重复调用get()方法需要显式处理null值非原子操作,多线程下不安全今天要介绍的方法,可以让你用一行代码优雅解决所有这些问题!方法的基本用法和优势与传统写法的对比分析多线程安全版本的实现Stream API的终极优化方案底层实现原理和性能优化建议一句话总结是Java 8为我们提供的Map操作利器,能让你的统计代码更简洁、更安全、更高效!// 合并两个列表});简单累加。
1264 0
|
SQL 缓存 NoSQL
执行SQL响应比较慢,你有哪些排查思路?
如果面试问你,执行SQL响应慢,你有哪些排查思路和解决方案?这是一位去某里面试的小伙伴跟我分享的面试真题,那今天我给大家来分享一下我的思路。
564 1
|
测试技术
评测 AlibabaCloud 阿里云国际版 香港轻量云服务器的性能和网络怎么样
评测 AlibabaCloud 阿里云国际版 香港轻量云服务器的性能和网络怎么样

热门文章

最新文章