【杂谈】死锁?NO,时间跳跃!
在日常开发或线上运维中,我们经常会遇到各种数据库异常,例如超时、死锁等。但有些问题,表面看似平常,背后却藏着意想不到的原因。
今天就分享一次由服务器时间跳跃引发的 MySQL 获取锁超时问题的排查过程。
问题现象:大量锁超时日志出现
某天系统日志中突然频繁出现如下报错信息:
Caused by: com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction
获取锁超时导致事务失败。
初步分析:死锁?
可能是出现死锁了,于是根据异常栈定位到问题代码,但发现该方法逻辑简单,仅修改一个entity,类似下面这样。(非真实业务代码)
// 仅更新用户的最后访问时间
user.setLastVisitTime(LocalDateTime.now());
userRepository.save(user);
强行分析(猜想),这个修改是每个请求都会改到的,由于在请求事务内,事务没提交就会一直锁着,直到请求完成。
但一个长期稳定运行的项目,请求不太可能突然变慢
深入排查:慢日志未出现异常
如果出现死锁,那么慢日志里面一定有记录。但实际排查袭来,慢日志并无User相关的慢查询。
蛛丝马迹:不太常见的日志
om.zaxxer.hikari.pool.HikariPool - HikariPool-1 - Thread starvation or clock leap detected (housekeeper delta=1m26s857ms76µs413ns).
翻阅日志,发现一条clock leap detected的异常记录。于是验证服务器时间,发现比本地环境快了40多秒。
真相大白:服务器时间跳跃引发误判
MySQL进行锁等待和事务超时时,依赖系统时间戳进行判断。当系统时间突然跳跃到未来时间,导致MYSQL误判。
至于跳跃原因,推测是 NTP 客户端在检测到时间漂移后进行了强制同步(stepping)操作,瞬间将时间快进了几十秒。
更近一步:有哪些操作会导致获取锁超时?
在 MySQL 使用 InnoDB 引擎的前提下,锁超时(Lock wait timeout exceeded)的出现通常有两个主要诱因:
1. 死锁(Deadlock)
最常见的原因就是死锁。死锁往往由于多个事务以不同顺序下修改相同资源,彼此持有对方需要的锁,造成互相等待、永远无法释放。
比如:
事务 A 修改顺序是:先改用户,再改订单;
事务 B 修改顺序是:先改订单,再改用户;
双方各自持有一个锁,又想获取对方的,结果就死锁了。
MySQL 会检测到死锁并主动中断其中一个事务。(这时候日志里就会出现Dealock报错了)
其实,只要在项目中统一规定 Entity 的修改顺序,大部分死锁是可以避免的。
2. 长事务导致的锁未及时释放
InnoDB 中,事务未提交期间会一直持有锁。如果事务执行时间过长,会导致其他并发请求长时间阻塞,最终抛出锁等待超时异常。
事务执行过长,常见原因包括:
Entity 修改过多
比如循环中逐个修改并保存,每次都save(),反复刷 SQL。事务中包含耗时操作
例如调用外部服务、HTTP 接口、微服务 RPC 等,尤其是对慢接口没有超时控制时。事务中存在显式等待
如Thread.sleep()用于调试、限速等场景,期间锁不会释放。
【杂谈】死锁?NO,时间跳跃!的更多相关文章
- 使用SQL Server 扩展事件来创建死锁的时间跟踪
我们通过SQL Server 2012图形界面来部署一个扩展事件跟踪会话.然后可以生成SQL脚本,在2008或2008 R2版本下运行类似的跟踪. 步骤1: 通过“Object Explorer”连接 ...
- 【DP】【P5615】 [MtOI2019] 时间跳跃
Description 给定 \(n\) 条边,第 \(i\) 条边的长度为 \(i\),每条边都有 \(50\%\) 的概率被选择,求如果选出的边能组成一个平面凸多边形,则方案的权值是方案中边的数量 ...
- DB2死锁的解决办法
db2 get snapshot for locks on sampledb2 get db cfg for sampledb2 update db cfg using dlchktime 10000 ...
- 时间,闰秒,及NTP
1.时间 格林尼治时间 GMT,以地球自转为准的时间,也叫世界时UT,但是由于自转速度会变化,所以后来不被作为标准. 世界协调时UTC,以原子钟为准,现在时间校准的标准就是原子钟. 2.闰秒 是指地球 ...
- 数据结构与算法(c++)——跳跃表(skip list)
今天要介绍一个这样的数据结构: 单向链接 有序保存 支持添加.删除和检索操作 链表的元素查询接近线性时间 ——跳跃表 Skip List 一.普通链表 对于普通链接来说,越靠前的节点检索的时间花费越低 ...
- 基于innodb_print_all_deadlocks从errorlog中解析MySQL死锁日志
本文是说明如何获取死锁日志记录的,不是说明如何解决死锁问题的. MySQL的死锁可以通过show engine innodb status;来查看,但是show engine innodb statu ...
- java和mysql之间的时间日期类型传递
摘自:http://blog.csdn.net/weinianjie1/article/details/6310770 MySQL(版本:5.1.50)的时间日期类型如下: datetime 8byt ...
- 一次查找sqlserver死锁的经历
查找bug是程序员的家常便饭,我身边的人喜欢让用户来重现问题.当然他们也会从正式服务器上下载错误log,然后尝试分析log,不过当错误不是那种不经思考就可识别的情况,他们就会将问题推向用户,甚至怪罪程 ...
- mysql和java的时间对应关系
引用:http://blog.csdn.net/xinghuo0007/article/details/51500923 MySQL(版本:5.1.50)的时间日期类型如下: datetime 8by ...
- linux环境下的时间编程
Linux下提供了丰富的api以供开发者们处理和时间相关的问题.然而这些接口看似各自为政实则有有着千丝万缕的联系,在学习和时间中引发了各种各样的混乱.因此时间处理成为了许多Linux开发者的梦魇,遇到 ...
随机推荐
- Codeforces Round 958 (Div. 2)
题目链接:Codeforces Round 958 (Div. 2) 总结:C因为常数没转\(long long\) \(wa\)两发,难绷. A. Split the Multiset fag:模拟 ...
- 正确停止Oracle expdp/impdp作业操作方法
1.使用命令查看在运行的作业名称,找到STATE是EXECUTING的作业名称. select job_name,state from dba_datapump_jobs; 2.再CMD命令窗口,键入 ...
- 云数据库MySQL多人协同开发实践
本文分享自天翼云开发者社区<云数据库MySQL多人协同开发实践>,作者:不知不觉 随着云计算技术的快速发展,云数据库作为云计算的重要组成部分,为企业提供了高效.灵活和可靠的数据存储和管理服 ...
- Q:plsql中文显示??处理
1.查询数据库字符集select userenv('language') from dual; 2.修改NLS_LANG环境变量:将NLS_LANG环境变量设置为正确的字符集 windows设置系统环 ...
- Linux驱动---按键
目录 一.Input子系统 1.1.简介 1.2.Input子系统构成 1.3.input_dev结构体 二.输入设备驱动开发流程 2.1.分配和初始化输入设备 2.2.注册设备 2.3.事件上报 2 ...
- Drasi Reactions SDK
Drasi Reactions SDK 是一个跨语言的开发工具包,用于实现和处理 Drasi 平台的 Reactions(反应器)功能.该 SDK 目前支持三种主流编程语言:JavaScript/Ty ...
- 天线的OTA测试
有源测试 (即OTA测试) 把使用综测仪的测试叫做有源测试(Active).使用有源测试的测试速度比较无源相对要慢,但是因为手机是一个复杂材料体,往往无源测试对发射性能的模拟是可信的,但是对于接收性能 ...
- element-ui实现table表格的嵌套(table表格嵌套)功能实现
最近在做电商类型的官网,希望实现的布局如下:有表头和表身,所以我首先想到的就是table表格组件. 表格组件中常见的就是:标题和内容一一对应:像效果图中的效果,只用基础的表格布局是不行的,因此我想 ...
- Github Copilot的使用方法和快捷键
GitHub Copilot是一款由GitHub和OpenAI共同开发的代码智能补全工具,它使用机器学习模型来为你提供代码建议和自动完成,可以加快开发过程并提高代码质量.下面是使用GitHub Cop ...
- MySQL - [04] 分布式部署&主从复制&读写分离
一.前言 Q1:为什么需要主从复制? 1.在业务复杂的系统中,有一条SQL语句需要锁表,导致暂时不能使用读的服务,那么就很影响运行中的业务.使用主从复制,让主库负责写,从库负责读,这样即使主库出现了锁 ...