一.现象

最近生产环境收到告警,异常堆栈信息如下

【异常日志】
### Error updating database. Cause: com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction

二.问题

某表锁等待超时。那么什么时候会产生锁等待

事务竞争同一行锁

1 下面我们做个实验,新建一张表student 

CREATE TABLE `student` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL COMMENT '姓名',
  `age` int DEFAULT NULL COMMENT '年龄',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb3 COMMENT='学生';

2 插入一条数据 

3 我们手动开始事务,对id=1的表进行更新

4 此时事务并未提交。我们开启另一个console窗口

5 经过一段时间后,报错Lock wait timeout。

结论

  1. 排他锁冲突
    当多个事务同时请求同一行记录的排他锁(如 UPDATEDELETESELECT ... FOR UPDATE),且前一个事务未提交或回滚时,后续事务会进入等待状态‌
    示例:事务 A 更新某行未提交,事务 B 尝试更新同一行时需等待锁释放

        由此结论可推断当springboot项目中多个线程运行同一个方法时,并对数据库某张表进行UPDATEDELETE等操作时,前一个事务尚未提交,后一个线程的事务就会造成锁等待,若超过最大锁等待时间,则mysql会抛出Lock wait timeout异常

如何解决Lock wait timeout异常

  1. 避免长时间不提交事务
    若事务长时间未提交或回滚(如大事务、意外中断未关闭连接),持有的锁未被释放,后续操作相同记录的事务将进入锁等待‌。

      避免长时间不提交事务,如批处理操作。可将事务拆分成小事务

     2. 尽量避免在事务中进行网络请求,因网络有波动,可能会造成方法执行较长时间

     3. 能用行锁就不用表锁

        当未对条件字段建立有效索引时,行锁可能升级为表锁,导致更多事务因表级锁竞争进入等待‌。

    

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐