记录一个@Transaction注解引发的bug

news2025/2/25 5:56:32

记录一个@Transactional(readOnly = true)注解引发的bug

一、问题代码和报错

1-1 问题代码模拟

引发这个问题的三大要素分别是:

  • 事务注解
  • 任意数据库操作
  • 数据库操作后执行耗时业务(耗时超过数据库配置的超时时间)
//1.这里是问题的核心之一:开启事务注解
@Transactional(readOnly = true)
public void testBug() {
    //2.这里是随便一个需要连接数据库的查询操作
    PageInfo<Needs> page = getPage(new NeedsQuery());
    //3.这里用睡5分钟来模拟执行业务
    try {
        Thread.sleep(5*60*1000);
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }
    //这里表示方法执行完成
    System.out.println("结束");
}

1-2 报错

Caused by: com.mysql.cj.jdbc.exceptions.CommunicationsException: The last packet successfully received from the server was 300,018 milliseconds ago. The last packet sent successfully to the server was 300,018 milliseconds ago. is longer than the server configured value of 'wait_timeout'. You should consider either expiring and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connection property 'autoReconnect=true' to avoid this problem.
	at com.mysql.cj.jdbc.exceptions.SQLError.createCommunicationsException(SQLError.java:174)
	at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:64)
	at com.mysql.cj.jdbc.ConnectionImpl.commit(ConnectionImpl.java:811)
	at com.zaxxer.hikari.pool.ProxyConnection.commit(ProxyConnection.java:387)
	at com.zaxxer.hikari.pool.HikariProxyConnection.commit(HikariProxyConnection.java)
	at org.springframework.jdbc.datasource.DataSourceTransactionManager.doCommit(DataSourceTransactionManager.java:333)
	... 107 common frames omitted

二、原因分析

先一句话总结报错原因:业务执行完成后提交事务时,数据库连接已经关闭,提交失败报错。

然后来细说这个报错是怎么产生的。

2-1 前提:MySQL配置

首先必须提到MySQL数据库的两个配置:

interactive_timeout:mysql在关闭一个非交互的连接之前所要等待的秒数
wait_timeout:mysql在关闭一个交互的连接之前所要等待的秒数

连接MySQL后通过命令可以查询到这两个配置的值:在没有配置的情况下,一般是默认28800秒,即8小时。

SHOW VARIABLES LIKE '%timeout%';

在这里插入图片描述

也就是,创建一个连接后,8小时没有通过这个连接执行任意操作,MySQL数据库为了节省资源,就会在数据库端断开这个连接。

2-2 报错分析

从报错日志可以看出:大致意思是数据库连接超时,在提交事务的时候报错。

at org.springframework.jdbc.datasource.DataSourceTransactionManager.doCommit(DataSourceTransactionManager.java:333)

这里的连接超时,就是指上面提到的:数据库连接超过了配置里设置的超时时间,自动断开了连接。

查询了下生产数据库的连接配置,发现我设置的超时时间是180秒。

把这个过程连贯地描述一下,也就是:我在创建了一个数据库连接之后,一段时间之后,再次使用这个数据库连接,发现连接已经断开,于是使用失败,程序抛出异常,于是抛出了这段错误日志。

The last packet successfully received from the server was 300,018 milliseconds ago. The last packet sent successfully to the server was 300,018 milliseconds ago. is longer than the server configured value of 'wait_timeout'. You should consider either expiring and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connection property 'autoReconnect=true' to avoid this problem.

按照日志里的描述,我是在超过了300秒之后再去使用这个连接,这当然是超过了我MySQL配置里的180秒的,程序的异常由此产生。

那么,为什么我要在把连接闲置了这么长一段时间之后,再次通过这个连接操作数据库呢。

这口锅就要扣到标题所说的注解@Transactional(readOnly = true)上了。

这里本来是个查询方法,不涉及改库的操作。但由于在方法头上加了@Transactional(readOnly = true)注解,意味着开启只读事务,所以这个方法涉及到的数据库操作,就会被事务管理。

所以原本的过程:

读数据库-》执行业务,

在事务的管理下,变成了:

开启事务-》读数据库-》执行业务-》提交事务。

image-20231011145807228

异常的发生就在最后一步的 提交事务 上。

最初开启事务时创建了数据库连接-》执行了超过180秒的业务-》程序试图用之前的数据库连接去提交事务-》而连接已经断开。

提交事务这一操作就会发生异常,报错由此产生。

三、解决方案

这里可以从两个方面去解决:

方案1:去掉事务

业务原本是读库操作,并没有必须开启事务的必要性,最简单的做法,当然是去掉事务注解,这样自然就不会因为提交事务时数据库连接已断开而报错。

方案2:修改MySQL配置

归根结底,异常的产生是由于数据库连接自动断开,那么我们按照错误日志的提示,把这个自动断开的时间设置得长一点,也能阻止异常的发生。

注意:直接修改查询到的MySQL配置只能改变本次连接里的设置,要想永久修改,必须在配置文件里修改后重启MySQL

[mysqld]
wait_timeout=180 # 这里改成你需要的时间,单位秒
interactive_timeout=180 # 这里改成你需要的时间,单位秒

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1087931.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于springboot实现实验室管理系统项目【项目源码+论文说明】

摘要 社会的发展和科学技术的进步&#xff0c;互联网技术越来越受欢迎。网络计算机的生活方式逐渐受到广大人民群众的喜爱&#xff0c;也逐渐进入了每个用户的使用。互联网具有便利性&#xff0c;速度快&#xff0c;效率高&#xff0c;成本低等优点。 因此&#xff0c;构建符合…

淘宝商品销量数据接口,淘宝API接口

淘宝商品销量数据接口是淘宝开放平台提供的一种API接口&#xff0c;通过该接口&#xff0c;商家可以获取到淘宝平台上的商品销量数据。 淘宝商品销量数据接口可以用于获取特定商品的销量数据、特定店铺的销量数据、特定类目的销量数据等。商家可以根据自己的需求来调用该接口&…

python基础教程:print()函数知识点总结

嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 print() 方法用于打印输出 语法&#xff1a; print(*objects, sep , end\n, filesys.stdout, flushFalse)参数 objects – 复数&#xff0c;表示可以一次输出多个对象。输出多个对象时&#xff0c;需要用 , 分隔。 sep – …

cas-server5.3自定义密码校验规则

前面几篇文章都是关于cas的,今天继续,cas有自己的一个加密配置.如果只是简单使用MD5或者SM3等加密算法进行加密的话,可以不需要再进行自定义操作,但是我们一般还会给用户密码加盐,这样的话原本的配置就不满足了,所以需要再自定义一个密码校验规则 实现PasswordEncoder接口 Pa…

数据报表的种类

根据报表使用频率不同&#xff0c;目的不同&#xff0c;使用群体不同&#xff0c;细化程度不同等情况&#xff0c;一般数据报表可以分为日常报表和临时报表&#xff0c;日常报表又分为管理报表和专题分析报表。 1. 日常报表 日常报表通常是指使用频率较高&#xff08;一般取3…

LED台灯控制芯片 LED调光芯片 LED驱动芯片AH6730

AH6730是一款专为LED台灯设计的多功能控制芯片。它采用电容式触摸控制&#xff0c;除了提供简单的开关控制功能外&#xff0c;还能实现从0到100或从100到0的无级调光&#xff0c;方便用户选择合适的亮度。该芯片的触摸板材兼容金属、亚克力板和硬塑料等材质。它具有两个通道的输…

Sketch macOS 支持m1 m2 Sketch 2023最新中文版

SketchUp Pro 2023是一款功能强大的三维建模软件&#xff0c;适用于建筑设计师、室内设计师、工程师和其他创意专业人士。以下是SketchUp Pro 2023的一些主要特点和功能&#xff1a; 三维建模&#xff1a;SketchUp Pro 2023允许用户以直观的方式创建三维模型。通过简单的绘图工…

【前端小技巧】如何使用 Eolink Apilkit 调用 Mock ?

在开发过程中&#xff0c;进度比较赶的情况下&#xff0c;前端人员当页面写完时&#xff0c;后台的接口还没写完&#xff0c;等要交付的时候后端才把接口给你&#xff0c;这个时候就很尴尬。 这个时候 Mock 就可以很好的解决这个问题&#xff0c;前端团队可以在 API 还没开发完…

CVE-2020-1938 Tomcat远程文件包含漏洞

漏洞简介 CVE-2020-1938是由长亭科技安全研究员发现的存在于 Tomcat 中的安全漏洞&#xff0c;由于 Tomcat AJP 协议设计上存在缺陷&#xff0c;攻击者通过 Tomcat AJP Connector 可以读取或包含 Tomcat 上所有 webapp 目录下的任意文件&#xff0c;例如可以读取 webapp 配置文…

whistle安卓手机抓包(图文详解)

1、安装node https://nodejs.org &#xff08;官网下载对应的node,一般推荐长期稳定版本 LTS&#xff09; 需要node的版本是大于 v0.10.0 查看自己本地node 版本号 node -v2、安装whistle npm i -g whistle3、开启whistle 补充说明&#xff1a; ● w2 stop&#xff1a;关闭…

ubuntu为可执行程序添加桌面图标

ubuntu为可执行程序添加桌面图标 1 在桌面目录&#xff0c;创建以.desktop为后缀的文件 cd ~/Desktop touch orb_slam.desktop 2 为desktopt添加执行权限 添加执行权限&#xff0c;才能实现双击运行&#xff0c;否则不能实现 chmod ax orb_slam.desktop3 编辑文件 ##(1)打…

Android+Appium自动化测试环境搭建及实操

1、Appium简介1.1 Appium概念1.2 Appium工作原理 2、Appium Server环境搭建2.1 Java JDK2.1.1 下载JDK2.1.2 运行exe安装JDK&#xff0c;设置安装路径2.1.3 设置环境变量2.1.4 验证安装结果 2.2 Android SDK2.2.1 下载安装Android SDK安装包2.2.2 下载platform-tools&#xff0…

php以半小时为单位,输出指定的时间范围

//可预订小时范围$hour [];for ($i$startHour*3600;$i<$endHour*3600;$i1800){//以半小时为单位输出$startHourItem date(H:i,strtotime(date(Y-m-d))$i);//小时开始$endHourItem date(H:i,strtotime(date(Y-m-d))$i1800);//当前时间再加半小时$hourItemStr $startHourI…

广州华锐互动:炼钢工厂VR仿真实训系统

随着科技的发展&#xff0c;我们的教育体系和职业培训方法也在迅速变化。其中&#xff0c;虚拟现实&#xff08;VR&#xff09;技术的出现为我们提供了一种全新的学习和培训方式。特别是在需要高度专业技能和安全性的领域&#xff0c;如钢铁冶炼。本文将探讨如何使用VR进行钢铁…

lark发消息艾特接口

首先访问"https://open.larksuite.com/api-explorer?apiNamebatch_get_id&projectcontact&resourceuser&versionv3"页面登录&#xff0c;然后点击左侧通过手机号或邮箱获取用户id&#xff0c;查询参数下面选择成员&#xff0c;搜索用户&#xff0c;点击…

探秘PMP和六西格玛的不同:哪一个能为你的职业生涯加分?

今天&#xff0c;我们将带你深入了解一项相对冷门但价值不菲的证书——六西格玛黑带。 可能你曾听说过PMP&#xff0c;但相比之下&#xff0c;六西格玛黑带的资源分享似乎较少&#xff0c;考试内容却更为广泛深入。这里&#xff0c;让我为你详细解析这一考试&#xff0c;带你进…

使用Python 获取天气数据

目录 前言 一、天气数据来源 二、Python获取天气数据 三、Python使用代理IP 四、Python获取天气数据实例 总结 前言 Python获取天气数据涉及到网络请求和数据解析两个方面&#xff0c;而代理IP则可以帮助我们有效地应对一些反爬虫的网站。本文将介绍如何在Python中获取天…

99%必用git指令

这14个Git命令&#xff0c;你都会吗&#xff1f; 必须了解的命令整理 1&#xff0c;git init 初始化一个新的Git仓库。 这将在当前目录中创建一个名为".git"的子目录&#xff0c;Git会将所有仓库的元数据存储在其中。 2&#xff0c;git clone 克隆一个已存在的仓…

PMP证书有什么用?考试条件是什么?

PMP证书摆在明面上的一个用处就是在招聘项目经理岗或者PMO岗的岗位要求中都会有一条&#xff1a;持有PMP证书优先。面试的时候&#xff0c;如果两个候选人的经历、经验、期望薪资都差不多&#xff0c;那么HR就会更倾向于有PMP/ACP等证书的候选人。 PMP是什么&#xff1f; PMP是…

常用的SQL语句

目录 前言 MySQL 创建数据库 创建表 字段类型 字段的特殊标识 SQL语句 向表中写入数据 SELECT语句 查询数据 INSERT INTO 语句 添加数据 UPDATE语句 修改数据 ​编辑 DELETE语句 删除数据 ​编辑 WHERE语句 AND和OR ORDER BY子句 COUNT(*)函数 前言 在MySQ…