@Transactional引发的数据库死锁问题及解决

 更新时间:2026年07月03日 16:07:04   作者:熬夜的王  
生产代码中updateById引发数据库死锁?别慌,这篇实战复盘教你快速定位长事务超时根源,从DBA反馈到@Transactional注解陷阱,我们一步步拆解解决方案,帮你避免类似生产事故

生产事故往往出现在一个不经意间的代码中产生的。

今天在生产代码中发生了数据库死锁的情况。操作由于调用updateById(Entity entity)的方法产生的。

Cause: com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction
    at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
    at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:199)
    at com.baomidou.mybatisplus.extension.activerecord.Model.updateById(Model.java:120)

由于是生产数据库,并且在测试环境同一功能未产生该问题。所以反馈给dba排查是否有死锁的SQL语句在执行中,等待dba回复的时间开始排查问题。

假设数据库返回的错误表名称为:table_test

排查过程

1.在生产通过界面或接口调用操作table_test表的数据。

** 结果:** 功能正常,能够正常更新数据。

2.分析代码,接口为post接口,主要代码逻辑如下:

	@Transactional
	public void updateBatchByCode(String code){
		List<Test1> list = service1.getListByCode(code);
		for(Test1 test1 : list){
			test1.setName("name1");
			service1.updateById(test1);
			List<Test2> list2 = service2.getListByTestCode(test1.getCode());
			for(Test2 test2 : list2){
				test2.setCode("code1");
				service2.updateById(test2);
			}
		}
	}

分析代码后觉得没有什么问题,因为代码逻辑比较简单。

这时也收到了DBA的回复:数据库无死锁语句,但是监测到有长时间未提交事务。 因为超过100秒未结束的事务,会被做超时处理。

再次分析代码,这时将目光定位在@Transactional这个注解上,我们知道该注解是用来将方法内的数据库操作放到一个事务中,如果执行过程中有异常进行数据回滚。

换个思路,这个就符合DBA提出的有长事务超时。

解决方案

去除@Transactional注解

去除了注解后,数据事务一致性得不到保障,当然我这里是因为该方法是用于处理特殊业务,所以去除了不要紧。大家在如果遇到该问题,建议:

将代码解耦,不要将很多的更新操作在一个长事务中使用。

后面将Transactional的源码翻下实现原理,到底为啥出现这个问题。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Java 代码实例解析设计模式之监听者模式

    Java 代码实例解析设计模式之监听者模式

    所谓监听者模式,我理解的是构建一个容器存放所有被监听的线程或对象,监听每个线程或对象发生的变化,若某个线程或对象触发指定规则,那么则对所有被监听的线程或对象根据业务需要做处理
    2021-10-10
  • Java ByteBuffer网络编程用法实例解析

    Java ByteBuffer网络编程用法实例解析

    这篇文章主要介绍了Java ByteBuffer网络编程用法实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-10-10
  • Java中Vector与ArrayList的区别详解

    Java中Vector与ArrayList的区别详解

    本篇文章是对Java中Vector与ArrayList的区别进行了详细的分析介绍,需要的朋友参考下
    2013-06-06
  • Mybatis查不到数据查询返回Null问题

    Mybatis查不到数据查询返回Null问题

    mybatis突然查不到数据,查询返回的都是Null,但是 select count(*) from xxx查询数量,返回却是正常的。好多朋友遇到这样的问题不知所措,下面小编通过本教程简单给大家说明下
    2016-08-08
  • Java代码注释规范(动力节点整理)

    Java代码注释规范(动力节点整理)

    代码注释是架起程序设计者与程序阅读者之间的通信桥梁,最大限度的提高团队开发合作效率。也是程序代码可维护性的重要环节之一。下面通过本文说一下我们在日常开发中使用的代码注释规范
    2017-03-03
  • java简易小游戏制作代码

    java简易小游戏制作代码

    这篇文章主要介绍了java简易小游戏制作代码,代码简单易懂,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-04-04
  • java实现模拟USB接口的功能

    java实现模拟USB接口的功能

    本文主要介绍了java实现模拟USB接口的功能,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • springboot 异步调用的实现方法

    springboot 异步调用的实现方法

    这篇文章主要介绍了springboot 异步调用的实现方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-04-04
  • spring注解@SneakyThrows用法及说明

    spring注解@SneakyThrows用法及说明

    @SneakyThrows是Lombok提供的一个注解,用于消除显式抛出或捕获受检异常的模板代码,使用该注解后,编译器会自动生成try-catch块来捕获这些异常,从而使代码更加简洁和易读
    2025-12-12
  • Springmvc实现文件下载2种实现方法

    Springmvc实现文件下载2种实现方法

    这篇文章主要介绍了Springmvc实现文件下载2种实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-03-03

最新评论