在日常开发或线上运维中,我们经常会遇到各种数据库异常,例如超时、死锁等。但有些问题,表面看似平常,背后却藏着意想不到的原因。

今天就分享一次由服务器时间跳跃引发的 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,时间跳跃!的更多相关文章

  1. 使用SQL Server 扩展事件来创建死锁的时间跟踪

    我们通过SQL Server 2012图形界面来部署一个扩展事件跟踪会话.然后可以生成SQL脚本,在2008或2008 R2版本下运行类似的跟踪. 步骤1: 通过“Object Explorer”连接 ...

  2. 【DP】【P5615】 [MtOI2019] 时间跳跃

    Description 给定 \(n\) 条边,第 \(i\) 条边的长度为 \(i\),每条边都有 \(50\%\) 的概率被选择,求如果选出的边能组成一个平面凸多边形,则方案的权值是方案中边的数量 ...

  3. DB2死锁的解决办法

    db2 get snapshot for locks on sampledb2 get db cfg for sampledb2 update db cfg using dlchktime 10000 ...

  4. 时间,闰秒,及NTP

    1.时间 格林尼治时间 GMT,以地球自转为准的时间,也叫世界时UT,但是由于自转速度会变化,所以后来不被作为标准. 世界协调时UTC,以原子钟为准,现在时间校准的标准就是原子钟. 2.闰秒 是指地球 ...

  5. 数据结构与算法(c++)——跳跃表(skip list)

    今天要介绍一个这样的数据结构: 单向链接 有序保存 支持添加.删除和检索操作 链表的元素查询接近线性时间 ——跳跃表 Skip List 一.普通链表 对于普通链接来说,越靠前的节点检索的时间花费越低 ...

  6. 基于innodb_print_all_deadlocks从errorlog中解析MySQL死锁日志

    本文是说明如何获取死锁日志记录的,不是说明如何解决死锁问题的. MySQL的死锁可以通过show engine innodb status;来查看,但是show engine innodb statu ...

  7. java和mysql之间的时间日期类型传递

    摘自:http://blog.csdn.net/weinianjie1/article/details/6310770 MySQL(版本:5.1.50)的时间日期类型如下: datetime 8byt ...

  8. 一次查找sqlserver死锁的经历

    查找bug是程序员的家常便饭,我身边的人喜欢让用户来重现问题.当然他们也会从正式服务器上下载错误log,然后尝试分析log,不过当错误不是那种不经思考就可识别的情况,他们就会将问题推向用户,甚至怪罪程 ...

  9. mysql和java的时间对应关系

    引用:http://blog.csdn.net/xinghuo0007/article/details/51500923 MySQL(版本:5.1.50)的时间日期类型如下: datetime 8by ...

  10. linux环境下的时间编程

    Linux下提供了丰富的api以供开发者们处理和时间相关的问题.然而这些接口看似各自为政实则有有着千丝万缕的联系,在学习和时间中引发了各种各样的混乱.因此时间处理成为了许多Linux开发者的梦魇,遇到 ...

随机推荐

  1. C# 开发工具Visual Studio 介绍

    Visual Studio Community (社区版) 这个版本的 Visual Studio 是免费的,具备以前 Professional 版的功能.使用时间有许可限制.它对开源项目和培训.学术 ...

  2. kali 安装

    准备 选用系统: kali-linux-2018.1-amd64.iso     kali-linux-2020.2-installer-amd64.iso 开始 2018版 1.选用图形化安装 2. ...

  3. 153:从shell提示符编辑文本文件

  4. ctfshow--web7 sql注入空格过滤

    ?id=10//union//select//1,database(),3//%23查看库名 查看表名 -1/**/union/**/select/**/1,(select/**/group_conc ...

  5. Palworld幻兽帕鲁世界参数修改最佳实践(Ubuntu)

    本文为您介绍对Palworld游戏世界参数进行修改的最佳实践. 操作场景 本文以Ubuntu操作系统为例,为您介绍通过Palworld专有镜像一键部署Palworld服务器后对游戏世界参数进行修改的具 ...

  6. 耳分解、双极定向和 P9394 Solution

    耳分解 设无向图 \(G'(V',E')\subset G(V,E)\),简单路径或简单环 \(P:x_1\to \dots \to x_k\) 被称为 \(G\) 关于 \(G'\) 的耳,当且仅当 ...

  7. MacSecureCRT配置

    一.调整连接服务器超时时间 Options->Global Options->General->Default Session-> 右侧Edit Default Setting ...

  8. kubernetes 集群中部署 nginx 服务

    kubernetes 部署nginx服务 本章节将介绍如何在kubernetes集群中部署一个nginx服务,并且能够对其进行访问. Namespace Namespace是kubernetes系统中 ...

  9. JUC并发—15.红黑树详解

    目录 1.红黑树的定义性质和推论 2.红黑树的旋转操作 3.红黑树之添加结点的方法 4.红黑树之删除结点的方法一 5.红黑树之删除结点的方法二 1.红黑树的定义性质和推论 (1)红黑树的定义和性质 ( ...

  10. 实测windows系统使用cmd搜索包含某个关键词的代码及PHP自动生成数据字典

    1.windows系统下进入cmd窗口-->替换自己的路径,执行下面命令 findstr /s /i "carlist" D:\phpstudy_pro\WWW\wxx\*. ...