当前位置: 首页 > article >正文

记录一次Spring事务失效导致的生产问题

一、背景介绍

公司做的是“聚合支付”业务,对接了微信、和包、数字人民币等等多家支付机构,我们提供统一的支付、退款、自动扣款签约、解约等能力给全国的省公司、机构、商户等。

同时,需要做对账功能,即支付机构将对账文件给到我们聚合支付,由我们进行如下三个定时任务:

1、入库:解析支付机构给的对账文件,解析每一笔订单,登记到数据库中;

2、对账:将支付机构的对账数据,与我们本地的对账数据,进行比对;

3、生成文件并下发:对完后,将对完账的我们的数据,按商户生成文件,并下发给商户的sftp机器。

我们的问题,就出在这个对账上面。

我们每天数据量都有500万-2000万笔订单数据,导致我们入库时,解析文件,每2000条数据提交数据库一次,压力还算能够承受;但是由于集团业务调整,导致我们每天的订单量,激增20%-50%。

而月初月末,交易量会更大,所以一到月末月初那阵子,每天的数据量都在两千万以上

这时由于支付机构给的对账数据更多,导致入库时间长,数据库DBA也提醒我们数据库压力大,所以我们研讨决定,牺牲部分时间,提升稳定性;将每2000条提交一次,修改为1000条修改一次;

导致入库的时间翻倍。这是业务背景

二、出现的异常现象

月中14号,修改了这个参数(2000笔提交一次->1000笔提交一次),一切正常。

到了月末(我们的业务月初、月末是高峰期,数据量更多),问题就来了:

我们的三个定时任务中的对账任务,对账突然卡住了,一直都没有动弹,出现告警;

由于一时看不出问题,临时决定使用:

重启大法。

重启后,并手动删除分布式锁后,对账任务恢复正常并下发对账文件给商户。

三、排查问题

前期排查,数据库资源cpu达到100%,以为是数据库的性能限制,导致对账线程池出现异常,无法获取连接导致的;但是后续我们调整多线程对账的线程数(10线程->8线程),数据库CPU占用降到90%多,但是第二天依然出现卡死现象。

无奈,继续排查:

通过使用jmap和jstack命令

# 打印 20250305.heapdump.hprof
# 这个命令用于生成Java进程的堆内存转储文件(Heap Dump),便于后续分析内存问题(如内存泄漏)
jmap -dump:live,format=b,file=20250305.heapdump.hprof  2365589# 打印 20250305.threaddump.txt
# 这个命令用于生成Java进程的线程转储(Thread Dump),帮助诊断线程阻塞、死锁、高CPU占用等问题。
jstack -l 2365589> 20250305.threaddump.txt

线程转储中看到,对数据库中有一个表的操作没有得到响应,就一直卡住

问了DBA的人员,确定,是这张表的行锁引起了问题。

于是,我们去看代码分析,经过我的仔细观察,与推翻各种不成立的假设后,终于被我定位到一个方法调用的错误:

如下是我们的大致调用图

可以看到解析并入库的主方法A,是带事务Transactional的

在下载文件完成后,调用方法B,再调用方法C,修改了一张状态表tb_status,修改状态为"下载成功"。

这里本意是方法C新开一个事务(REQUIRES_NEW),这样修改完后,单独提交;

后面的方法E,也是同样的打算。

可是写这段代码的时候没想到,spring事务注解是有可能会失效的;

在 Spring 中,当一个类中的方法 自调用(即类内部方法A调用方法B)时,如果方法B上标注了 @Transactional 事务注解,事务会失效。这是由 Spring 的 AOP 代理机制导致的。

在我们这个案例中,正是出现了这样的情况:方法A,调用B,再调用C时,以为C会新开一个事务去直接提交,但是没想到事务失效了,事务C的修改,并没有直接提交;

一直等到,文件解析入库(耗时很长)后,方法A的整个流程结束,才一起提交;

导致这一段时间内,定时任务“对账”想修改这一行数据,无法修改,导致卡住。

为什么之前没事呢?这代码跑了很久都没事啊,怎么回事呢?这就要结合我前面罗里吧嗦说的一大堆业务来看了,本来因为集团切业务,导致我们系统业务量暴增,又是月初月末,数据量更加大;光是一个微信商户给的对账文件就有2.5GB多(900多万,接近一千万订单);

导致解析文件并入库时间由10分钟左右,增加到45分钟以上。我们的“对账”定时任务,每15分钟执行一次,而入库的这45分钟,由于对tb_status的修改,一直没有提交,故而“对账”任务,意图修改tb_status的状态时,一直拿不到行锁修改数据,就卡住了。

四、解决方案

既然知道问题的原因,那么解决方案,我相信读者有很多种。

第一:方法A不带事务,让其他自己的事务,各自以非事务的方式,自动提交(此方式一定要根据自己业务逻辑的上下文来看,不能盲目各自提交)

第二:修改方法C上注解的位置,移动至方法B使其生效

经过评估,我们是选择了第一种。

另外,附上spring事务失效的几种场景:

1、如果被@Transactional修饰的方法,不是public的,那么事务会失效;

2、一个类中的方法 自调用(即类内部方法A调用方法B)时,如果方法B上标注了 @Transactional 事务注解,事务会失效。

3、如果一个方法是final的,那么加@Transactional事务也是无法生效的

4、被try-catch捕获了异常,没有往外抛出,那么spring事务会认为方法,没有发生异常,就不会回滚,事务失效

5、数据库表本身不支持事务,导致事务失效,例如InnoDB就不支持事务

相关文章:

记录一次Spring事务失效导致的生产问题

一、背景介绍 公司做的是“聚合支付”业务,对接了微信、和包、数字人民币等等多家支付机构,我们提供统一的支付、退款、自动扣款签约、解约等能力给全国的省公司、机构、商户等。 同时,需要做对账功能,即支付机构将对账文件给到…...

深度学习实战:用TensorFlow构建高效CNN的完整指南

一、为什么每个开发者都要掌握CNN? 在自动驾驶汽车识别路标的0.1秒里,在医疗AI诊断肺部CT片的精准分析中,甚至在手机相册自动分类宠物的日常场景里,卷积神经网络(CNN)正悄然改变着我们的世界。本文将以工业…...

算法 之 贪心思维训练!

文章目录 从最大/最小开始贪心2279.装满石头的背包的最大数量2971.找到最大周长的多边形 从最左、最右开始贪心2712.使所有字符相等的最小成本 划分型贪心1221.分割平衡字符串 贪心策略在处理一些题目的时候能够带来意想不到的效果 从最小/最大开始贪心,优先考虑最小…...

从0到1构建AI深度学习视频分析系统--基于YOLO 目标检测的动作序列检查系统:(1)视频信息的获取与转发

文章大纲 基于YOLO的动作序列检查系统架构设计系统架构图实时视频传输协议技术对比视频流 常见协议对比表三、WebSocket内网传输设计方案四、样例程序(Python + JavaScript)五、性能优化建议新兴技术预警参考文献提示词参考基于YOLO的动作序列检查系统架构设计 系统架构图 #…...

大语言模型学习--LangChain

LangChain基本概念 ReAct学习资料 https://zhuanlan.zhihu.com/p/660951271 LangChain官网地址 Introduction | 🦜️🔗 LangChain LangChain是一个基于语言模型开发应用程序的框架。它可以实现以下应用程序: 数据感知:将语言模型…...

【PCIe 总线及设备入门学习专栏 4.5 -- PCIe 中断 MSI 与 MSI-X 机制介绍】

文章目录 PCI 设备中断机制PCIe 设备中断机制PCIe MSI 中断机制MSI CapabilityMSI-X 中断机制MSI-X capabilityMSI-X TablePBAMSI-X capability 解析MSI/MSI-X 操作流程扫描设备配置设备MSI 配置MSI-X 配置中断触发与处理PCI 设备中断机制 以前的PCI 设备是支持 物理上的 INTA…...

wxWidgets GUI 跨平台 入门学习笔记

准备 参考 https://wiki.wxwidgets.org/Microsoft_Visual_C_NuGethttps://wiki.wxwidgets.org/Tools#Rapid_Application_Development_.2F_GUI_Buildershttps://docs.wxwidgets.org/3.2/https://docs.wxwidgets.org/latest/overview_helloworld.htmlhttps://wizardforcel.gitb…...

valgrind 检测多线程 bug,检测 并发 bug concurrent bug parallel bug

valgrind --toolhelgrind ./your_program 如果检测的对象是大型程序,可以设定仅在某些函数中开启 valgrind 的检测: Valgrind 提供了一些客户请求(client requests),可以在代码中插入特定的宏来控制 Valgrind 的行为。…...

OpenMCU(一):STM32F407 FreeRTOS移植

概述 本文主要描述了STM32F407移植FreeRTOS的简要步骤。移植描述过程中,忽略了Keil软件的部分使用技巧。默认读者熟练使用Keil软件。本文的描述是基于OpenMCU_FreeRTOS这个工程,该工程已经下载放好了移植stm32f407 FreeRTOS的所有文件 OpenMCU_FreeRTOS工…...

割平面法的理解

割平面法的理解 1. 简介 割平面法(Cutting Plane Method)用于求解整数规划问题,通过逐步添加线性约束(割平面)逼近整数解。本文以Gomory割平面法为例,结合简单示例拆解核心步骤。 2. 示例详解 问题描述 …...

[自动驾驶-传感器融合] 多激光雷达的外参标定

文章目录 引言外参标定原理ICP匹配示例参考文献 引言 多激光雷达系统通常用于自动驾驶或机器人,每个雷达的位置和姿态不同,需要将它们的数据统一到同一个坐标系下。多激光雷达外参标定的核心目标是通过计算不同雷达坐标系之间的刚性变换关系&#xff08…...

C++ 学习(八)(模板,可变参数模板,模板专业化(完整模板专业化,部分模板专业化),类型 Traits,SFINAE(替换失败不是错误),)

C 模板 C 中的模板是一项强大的功能,允许您编写通用代码,这意味着您可以编写可以处理不同数据类型的单个函数或类。这意味着您无需为要使用的每种数据类型编写单独的函数或类。 模板函数 要创建模板函数,请使用 关键字,后跟类型…...

AI---DevOps常备工具(‌AI-Integrated DevOps Essential Tools)

AI---DevOps常备工具 技术领域正在迅速发展,随着我们步入 2025 年,有一点是明确的:人工智能(AI)不再只是一个流行词,它是每个 DevOps 工程师都需要掌握的工具。随着云环境的复杂性增加、对更快部署的需求以…...

题目梳理2025[长期更新]

题目梳理 组合类题目(2025年3月5日) 组合总数1,组合总数2,组合总数3 -> 递归回溯的思想 组合总数4 -> 爬楼的思想,动态规划,确定递归边界,确定递归入口,最后一步怎么走的思想...

Maven 中 SNAPSHOT 版本与 RELEASE 版本的区别

Maven 仓库分为 Snapshot 快照仓库和 Release 发行仓库两种类型的仓库。Snapshot 快照仓库用于保存 SNAPSHOT 版本,Release 发行仓库用于保存 RELEASE 版本。 SNAPSHOT 是一种特殊的版本标识,主要用于表示项目的不稳定、正在开发中的版本,而…...

JavaScript 知识点整理

1. 什么是AST?它在前端有哪些应用场景? AST Abstract Syntax Tree抽象语法树,用于表达源码的树形结构 应用: Babel:一个广泛使用的 JS 编译器,将ES6 或 JSX 等现代语法转换为兼容性较好的 ES5 代码。Esl…...

迷你世界脚本出生点接口:Spawnport

出生点接口:Spawnport 彼得兔 更新时间: 2023-04-26 10:19:56 具体函数名及描述如下: 序号 函数名 函数描述 1 getSpawnPoint(...) 获取默认出生点 2 setSpawnPoint(...) 设置出生点位置 3 getChunkValidSpawnPos(...) 获取区块有效刷新点…...

鸿蒙与DeepSeek深度整合:构建下一代智能操作系统生态

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。 https://www.captainbed.cn/north 目录 技术融合背景与价值鸿蒙分布式架构解析DeepSeek技术体系剖析核心整合架构设计智能调度系统实现…...

利用行波展开法测量横观各向同性生物组织的生物力学特性|文献速递-医学影像人工智能进展

Title 题目 Measurement of biomechanical properties of transversely isotropic biological tissue using traveling wave expansion 利用行波展开法测量横观各向同性生物组织的生物力学特性 01 文献速递介绍 纤维嵌入结构在自然界中普遍存在。从脑白质(罗曼…...

AR配置静态IP双链路负载分担示例

AR配置静态IP双链路负载分担示例 适用于大部分企业网络出口 业务需求: 运营商1分配的接口IP为100.100.1.2,子网掩码为255.255.255.252,网关IP为100.100.1.1。 运营商2分配的接口IP为200.200.1.2,子网掩码为255.255.255.248&am…...

文件操作(详细讲解)(1/2)

你好这里是我说风俗,希望各位客官点点赞,收收藏,关关注,各位对我的支持是我持续更新的动力!!!!第二期会马上更的关注我获得最新消息哦!!!&#xf…...

[AI]从零开始的so-vits-svc歌声推理及混音教程

一、前言 在之前的教程中已经为大家讲解了如何安装so-vits-svc以及使用现有的模型进行文本转语音。可能有的小伙伴就要问了,那么我们应该怎么使用so-vits-svc来进行角色歌曲的创作呢?其实歌曲的创作会相对麻烦一些,会使用到好几个软件&#x…...

华为OD机试-停车场最大距离(Java 2024 E卷 100分)

题目描述 停车场有一排车位,用 0 表示空位,1 表示已停车。至少有一辆车停在车位上,也至少有一个空位。为了防剐蹭,需要找到一个空位,使得该空位与最近的车辆之间的距离最大。返回这个最大距离。 输入描述 一个用半角逗号分隔的停车标识字符串,停车标识为 0 或 1,0 表示…...

SpringMVC控制器定义:@Controller注解详解

文章目录 引言一、Controller注解基础二、RequestMapping与请求映射三、参数绑定与数据校验四、RestController与RESTful API五、控制器建议与全局处理六、控制器测试策略总结 引言 在SpringMVC框架中,控制器(Controller)是整个Web应用的核心组件,负责处…...

免费分享一个软件SKUA-GOCAD-2022版本

若有需要,可以下载。 下载地址 通过网盘分享的文件:Paradigm SKUA-GOCAD 22 build 2022.06.20 (x64).rar 链接: https://pan.baidu.com/s/10plenNcMDftzq3V-ClWpBg 提取码: tm3b 安装教程 Paradigm SKUA-GOCAD 2022版本v2022.06.20安装和破解教程-CS…...

学习threejs,使用LineBasicMaterial基础线材质

👨‍⚕️ 主页: gis分享者 👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍⚕️ 收录于专栏:threejs gis工程师 文章目录 一、🍀前言1.1 ☘️THREE.LineBasicMaterial1.…...

python保留字及作用

在 Python 中,保留字(Reserved Keywords)是具有特殊意义和用途的单词,不能用作变量名、函数名或标识符。以下是 Python 的保留字及其作用: Python 保留字列表 保留字作用False布尔值,表示假。None表示空值…...

java面试题(一)基础部分

1.【String】StringBuffer和StringBuilder区别? String对象是final修饰的不可变的。对String对象的任何操作只会生成新对象,不会对原有对象进行操作。 StringBuilder和StringBuffer是可变的。 其中StringBuilder线程不安全,但开销小。 St…...

Mac mini M4安装nvm 和node

先要安装Homebrew(如果尚未安装)。在终端中输入以下命令: /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)" 根据提示操作完成Homebrew的安装。 安装nvm。在终端中输入以下命令&#xf…...

Ubuntu20.04双系统安装及软件安装(四):国内版火狐浏览器

Ubuntu20.04双系统安装及软件安装(四):国内版火狐浏览器 Ubuntu系统会自带火狐浏览器,但该浏览器不是国内版的,如果平常有记录书签、浏览记录、并且经常使用浏览器插件的习惯,建议重装火狐浏览器为国内版的…...