news 2026/8/21 7:31:28

MySQL事务与Spring事务的关系

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
MySQL事务与Spring事务的关系

MySQL事务与Spring事务的关系

  • 1. MySQL事务(数据库层)
  • 2. Spring事务(应用层)
  • 3. 两者关系详解
    • 3.1 层级关系
    • 3.2 Spring对MySQL事务的封装
  • 4.Spring事务的工作流程
    • 4.1 Spring在开启事务时做了什么?
    • 4.2 Spring何时关闭自动提交?
    • 4.3 Spring对自动提交的设置是会话级别的吗?
    • 4.4 与手动使用命令行的对比
  • 5.Spring事务的本质是线程与连接的绑定吗?

MySQL事务是数据库层面的原生事务机制,而Spring事务是应用层基于MySQL事务(或其他数据库事务)构建的声明式/编程式事务抽象,也就是说,Sprnig事务是 数据库事务在 Java框架层面的封装和增强,本质上还是依赖数据库的事务机制


1. MySQL事务(数据库层)

-- MySQL原生事务示例STARTTRANSACTION;UPDATEaccountsSETbalance=balance-100WHEREid=1;UPDATEaccountsSETbalance=balance+100WHEREid=2;COMMIT;-- 或 ROLLBACK

MySQL的事务模型:

  1. 自动提交模式(autocommit:MySQL默认每个SQL语句都是一个独立事务,执行后自动提交。这就是“自动提交”模式(autocommit=1)。
  2. 显式开启事务:当你执行BEGINSTART TRANSACTION或 设置autocommit=0时,就进入了显式事务模式。后续多个SQL将成为一个整体,直到你执行COMMITROLLBACK

2. Spring事务(应用层)

这篇文章的最后会说明使用Spring事务的3种方式(本质上就两种,声明式和编程式)

  • 事务模板TransactionTemplate、事务管理器和DataSource数据源三者的关系

下面给出一个例子,使用的是 Spring的声明式事务(@Transactional)

@Service@Transactional// Spring事务注解publicclassTransferService{@AutowiredprivateAccountRepositoryrepository;publicvoidtransfer(Longfrom,Longto,BigDecimalamount){repository.debit(from,amount);repository.credit(to,amount);}}

3. 两者关系详解

3.1 层级关系

应用层:Spring事务管理器 (PlatformTransactionManager) ↓ 驱动层:JDBC事务 (Connection.setAutoCommit(false)) ↓ 数据库层:MySQL事务引擎 (InnoDB)

3.2 Spring对MySQL事务的封装

// Spring的事务管理器实际是对JDBC连接的封装publicclassDataSourceTransactionManagerimplementsPlatformTransactionManager{@OverrideprotectedvoiddoBegin(Objecttransaction,TransactionDefinitiondefinition){Connectioncon=dataSource.getConnection();con.setAutoCommit(false);// 关闭自动提交 → 开启MySQL事务con.setTransactionIsolation(definition.getIsolationLevel());}}

4.Spring事务的工作流程


4.1 Spring在开启事务时做了什么?

在【3.2 Spring对MySQL事务的封装】小节,我们可以看到 事务管理器DataSourceTransactionManager 中有这样一行代码:

con.setAutoCommit(false);// 关闭自动提交 → 开启MySQL事务

Q:Spring在开启事务时做了什么?
A:Spring会(在必要时)帮我们 关闭自动提交,但处理得非常智能。

整个过程如下图所示,清晰地展示了Spring如何在一个事务生命周期内,精细地管理 数据库连接 的自动提交状态:


上面这个Spring事务流程,我们可以从【事务模板TransactionTemplate】的核心方法execute(TransactionCallback action)看起,

TransactionTemplate#execute()// 1- 入口AbstractPlatformTransactionManager#getTransaction()// 获取事务AbstractPlatformTransactionManager#startTransaction()DataSourceTransactionManager#doBegin()// 这个方法内部关闭自动提交if(con.getAutoCommit()){txObject.setMustRestoreAutoCommit(true);con.setAutoCommit(false);}TransactionTemplate#execute()// 2- 这个方法会执行回调(也就是我们的业务逻辑)// 成功则执行commit(); 3- 失败则执行rollbackDataSourceTransactionManager#doCleanupAfterCompletion// 4- 不管是commit还是rollback,都会调用这个方法,而这个方法内部会开启自动提交if(txObject.isMustRestoreAutoCommit()){con.setAutoCommit(true);}

4.2 Spring何时关闭自动提交?

当一个需要事务的方法被调用(例如,传播行为为REQUIRED且当前没有事务),事务管理器(DataSourceTransactionManager)在doBegin()方法中,会从连接池拿到一个连接,然后立即执行con.setAutoCommit(false)。这对应于MySQL的START TRANSACTION

4.3 Spring对自动提交的设置是会话级别的吗?

  • 是,但Spring做了完美的封装和恢复。
    • setAutoCommit(false)确实是针对这个Connection会话的设置。
    • 关键点:Spring不会让这个设置“污染”连接。在事务结束(提交或回滚)后,Spring会立刻执行con.setAutoCommit(true),将连接恢复为默认的自动提交模式,然后再将连接归还给连接池
    • 为什么这么做?因为连接池中的连接是重用的。如果连接带着autoCommit=false的状态被其他不声明事务的业务代码拿到,它的所有操作都会意外地处于一个未提交的长事务中,导致数据看不到、锁无法释放等严重问题。Spring的“恢复”机制保证了连接状态的干净。

4.4 与手动使用命令行的对比

操作手动命令行Spring 声明式事务
开启事务START TRANSACTION;SET autocommit=0;DataSourceTransactionManager.doBegin()中调用con.setAutoCommit(false)
提交事务COMMIT;事务成功后,调用con.commit()
回滚事务ROLLBACK;发生异常时,调用con.rollback()
恢复状态需手动SET autocommit=1;自动在提交/回滚后调用con.setAutoCommit(true)

总结Spring事务是基于MySQL事务的【高级抽象】,提供了更便捷的声明式编程模型和额外的企业级特性,但最终都是通过MySQL的事务引擎实现数据一致性保证


5.Spring事务的本质是线程与连接的绑定吗?


完全正确,这是Spring管理事务的基石。

  • 1. 核心机制
    • Spring事务管理的核心,就是通过事务上下文TransactionSynchronizationManager,将当前开启的事务对应的 数据库连接(Connection)绑定到 当前执行线程(ThreadLocal)上
    • Spring 事务上下文(TransactionSynchronizationManager)基于 ThreadLocal 实现,无法跨线程传播。所以说,在使用线程池时要注意:提交到线程池的任务,其事务管理完全独立于主线程,多线程会带来多个独立的事务(因为每个线程有自己独立的数据库连接和事务上下文)。
    • 由此可知,Spring事务传播行为解决的是在单一线程中,多个事务方法(如methodA调用了methodB)相互调用时,事务边界应该如何定义和传播
    • DataSourceTransactionManager#doGetTransaction()。
  • 2. 后续所有操作:在同一线程、同一事务内的所有数据库操作(通过MyBatis、JdbcTemplate等),都会从ThreadLocal中获取这个被绑定的、唯一的连接,从而保证它们都在同一个数据库事务中执行。
  • 3. 动态数据源联动DataSourceAspect先于事务拦截器执行,将数据源Key(如SHARDING)设置到ThreadLocal。当事务管理器获取连接时,动态数据源通过determineCurrentLookupKey()读取这个Key,从而路由到正确的物理连接,再把这个物理连接绑定到线程。关于数据源动态路由见文章:Sharding分库分表复杂SQL之数据源路由

下面这个是上面Spring事务工作流程图的 mermaid代码:

// mermaidsequenceDiagram participant SC asServiceCodeparticipant TI asTransactionInterceptorparticipant TM asDataSourceTransactionManagerparticipant CP as 数据库连接池 participantConnas 物理ConnectionparticipantMySQLSC->>TI:调用@Transactional方法 TI->>TM:getTransaction()TM->>CP:获取连接(getConnection)CP->>Conn:取出/新建连接NoteoverConn,MySQL:连接初始状态:<br/>autoCommit=true(默认)TM->>Conn:conn.setAutoCommit(false)Noteover TM,Conn:关键步骤:关闭自动提交<br/>(开启实物事务) TM->>TM:将连接绑定到当前线程 TM-->>TI:返回事务状态 TI->>SC:执行业务SQL SC->>TM:(框架)获取线程绑定的连接 TM-->>SC:返回连接 SC->>MySQL:执行INSERT/UPDATE...SC-->>TI:业务执行完毕 alt 成功 TI->>TM:commit()TM->>Conn:conn.commit()TM->>Conn:conn.setAutoCommit(true)else失败 TI->>TM:rollback()TM->>Conn:conn.rollback()TM->>Conn:conn.setAutoCommit(true)endNoteover TM,Conn:关键清理:恢复连接的原始状态 TM->>TM:解绑连接,释放线程资源 TM->>CP:归还连接(close)NoteoverConn,CP:连接状态已恢复为<br/>autoCommit=true,可供下次使用
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/20 6:47:41

敏感词库自定义配置:LobeChat内容安全控制

敏感词库自定义配置&#xff1a;LobeChat内容安全控制 在企业开始将大语言模型&#xff08;LLM&#xff09;深度集成到客服、知识问答甚至内部协作系统中的今天&#xff0c;一个看似简单却极为关键的问题浮出水面&#xff1a;如何防止AI说出不该说的话&#xff1f; 想象这样一…

作者头像 李华
网站建设 2026/8/20 12:37:16

别再问 “要不要做等保” 了!一文讲清合规要求与企业风险

在数字化深入推进的今天&#xff0c;仍有不少企业纠结“是否需要做等保”。答案其实早已明确&#xff1a;等保不是可选项&#xff0c;而是企业运营的“必修课”。尤其2025年等保新规落地后&#xff0c;合规要求更趋严格&#xff0c;忽视等保不仅面临法律风险&#xff0c;更可能…

作者头像 李华
网站建设 2026/8/19 6:40:59

GraniStudio零代码平台如何使用快速创建算子功能?

GraniStudio零代码平台提供一种快速创建算子功能,使用此功能将自动排版算子间距并对齐。 使用此功能使用键盘输入Ctrl E按键即可将创建窗口调出。在输入框中输入需要创建算子&#xff0c;将在列表中显示, 使用键盘Tab按键切换并选择需要创建算子, 使用键盘 Enter按键即可在对应…

作者头像 李华
网站建设 2026/8/20 4:25:24

学网络安全要学历吗?

网络安全是一门门槛低、薪资高的技术活&#xff0c;而且该领域注重实践能力&#xff0c;对学历没有强制性的限制&#xff0c;适合所有人学习。虽说如此&#xff0c;但不少人依然心存疑问&#xff1a;学网络安全需要什么学历?一起来探讨一下。学网络安全需要什么学历?学习网络…

作者头像 李华
网站建设 2026/8/21 0:20:22

DAY 40 Dataset类和Dataloader类

一、Dataset类的_getitem_和_len_方法 在 PyTorch 中&#xff0c;torch.utils.data.Dataset 是所有自定义数据集的抽象基类&#xff0c;它规定了数据集必须实现两个核心方法&#xff1a;__len__ 和 __getitem__。这两个方法是 DataLoader 加载数据的基础&#xff0c;决定了数据…

作者头像 李华
网站建设 2026/8/20 9:32:37

视觉盛宴:鸿蒙Canvas/Animation与Flutter CustomPaint的深度协同

前言&#xff1a;当“声明式UI”遇上“Skia引擎” 在鸿蒙Flutter的混合开发中&#xff0c;我们经常会遇到一种尴尬的局面&#xff1a;原生侧&#xff08;ArkUI&#xff09;画了一个漂亮的图表&#xff0c;Flutter侧&#xff08;Widget&#xff09;也画了一个&#xff0c;但两者…

作者头像 李华