事务的传播行为,分别在spring和mysql中讲解

发布于:2025-07-21 ⋅ 阅读:(17) ⋅ 点赞:(0)

目录

一、Spring 中的事务传播行为

1. 七种传播行为的详细说明

2. 关键特点

二、MySQL 中的事务“传播”相关机制

1. 核心机制:事务的嵌套与交互

2. 与 Spring 传播行为的关联

三、核心区别与联系


事务的传播行为是指当一个事务方法(或操作)调用另一个事务方法(或操作)时,两个事务之间的交互规则(如是否共用一个事务、是否新建事务、是否暂停当前事务等)。其核心是解决“嵌套事务场景下,事务边界如何划分”的问题。

一、Spring 中的事务传播行为

Spring 作为 Java 企业级框架,在应用层(代码层面) 定义了七种事务传播行为,用于控制不同方法间的事务交互逻辑。这些行为由 org.springframework.transaction.annotation.Propagation 枚举类定义,本质是通过 AOP 代理机制控制事务的创建、加入、暂停或提交/回滚。

1. 七种传播行为的详细说明

传播行为

含义及行为规则

典型场景

PROPAGATION_REQUIRED(默认)

如果当前存在事务,则加入该事务;如果当前没有事务,则新建一个事务。

最常用场景,例如“下单”方法调用“扣库存”和“减余额”方法,三者共用一个事务,要么全成功,要么全回滚。

PROPAGATION_SUPPORTS

如果当前存在事务,则加入该事务;如果当前没有事务,则以“非事务方式”执行。

适用于“可选事务”的操作,例如“查询订单详情”(可在事务内执行,也可单独执行,不强制事务)。

PROPAGATION_MANDATORY

如果当前存在事务,则加入该事务;如果当前没有事务,则直接抛出异常(IllegalTransactionStateException)。

强制依赖当前事务的操作,例如“日志记录必须在主事务内执行”,如果调用方没有事务则报错。

PROPAGATION_REQUIRES_NEW

无论当前是否存在事务,都新建一个事务;如果当前存在事务,则将当前事务“暂停”,待新事务完成后再恢复。

需要“独立事务”的场景,例如“下单失败时记录失败日志”,即使下单事务回滚,日志事务仍需提交(确保日志不丢失)。

PROPAGATION_NOT_SUPPORTED

以“非事务方式”执行;如果当前存在事务,则将当前事务“暂停”,待非事务操作完成后再恢复。

适用于“不需要事务”的操作(如耗时的查询或报表生成),避免长期占用事务资源导致锁竞争。

PROPAGATION_NEVER

以“非事务方式”执行;如果当前存在事务,则直接抛出异常。

严格禁止在事务内执行的操作,例如“批量数据同步”(必须独立执行,防止被其他事务阻塞)。

PROPAGATION_NESTED

如果当前存在事务,则在当前事务内创建一个“嵌套事务”(通过数据库保存点 savepoint 实现);如果当前没有事务,则等同于 REQUIRED

需“部分回滚”的场景,例如“批量插入100条数据,前50条失败时仅回滚前50条,继续执行后50条”(通过保存点控制回滚范围)。

2. 关键特点
  • Spring 的传播行为是逻辑层面的控制,依赖事务管理器(如 DataSourceTransactionManager)与底层数据库的事务支持(如 MySQL InnoDB)。
  • 传播行为的生效需要通过 @Transactional 注解(或 XML 配置)声明,并由 Spring AOP 代理实现(注意:同类方法内部调用可能因未经过代理而导致传播行为失效)。

二、MySQL 中的事务“传播”相关机制

MySQL 作为数据库,没有像 Spring 那样定义明确的“传播行为”枚举,但在数据库层面存在事务交互的底层机制,其行为受存储引擎(仅 InnoDB 支持事务)、事务隔离级别、是否自动提交等因素影响。

1. 核心机制:事务的嵌套与交互

MySQL 中“事务传播”更多体现在嵌套事务场景(如存储过程中调用事务、客户端代码中嵌套执行事务)的处理逻辑,核心规则如下:

  • 默认不支持“真正的嵌套事务”
    InnoDB 是“扁平事务模型”,即一个会话中只能有一个活跃事务。如果在一个事务内尝试通过 START TRANSACTION 开启新事务,MySQL 会隐式提交当前事务,再开启新事务(等价于先执行 COMMIT,再新建事务)。
    例如:
START TRANSACTION; -- 开启事务 T1
INSERT INTO t1 VALUES (1); -- T1 中的操作
START TRANSACTION; -- 隐式提交 T1,再开启新事务 T2
INSERT INTO t2 VALUES (2); -- T2 中的操作
COMMIT; -- 提交 T2(此时 T1 已被隐式提交)
  • 通过保存点(SAVEPOINT)模拟嵌套事务
    虽然不支持多个独立事务的嵌套,但 InnoDB 支持 SAVEPOINT(保存点),可在一个事务内设置多个保存点,实现“部分回滚”(回滚到指定保存点,而非整个事务)。这与 Spring 的 PROPAGATION_NESTED 传播行为对应。
    例如:
START TRANSACTION; -- 开启事务 T
INSERT INTO t1 VALUES (1);
SAVEPOINT sp1; -- 设置保存点 sp1
INSERT INTO t1 VALUES (2);
ROLLBACK TO sp1; -- 回滚到 sp1,此时 t1 中仅保留 (1)
INSERT INTO t1 VALUES (3);
COMMIT; -- 提交 T,最终 t1 中有 (1, 3)
  • 事务的自动提交(autocommit)影响
    MySQL 默认 autocommit=ON(每个 SQL 语句自动作为一个事务提交)。若需手动控制事务,需先执行 SET autocommit=OFF,再通过 START TRANSACTION 开启事务,最后用 COMMITROLLBACK 结束。
    autocommit=ON 时,嵌套执行 SQL 会自动分拆为多个独立事务,类似 Spring 的 PROPAGATION_REQUIRES_NEW,但粒度是单条 SQL。

2. 与 Spring 传播行为的关联
  • Spring 的 PROPAGATION_REQUIRES_NEW 依赖 MySQL 支持“独立事务的提交/回滚”(即一个事务的提交/回滚不影响其他事务)。
  • Spring 的 PROPAGATION_NESTED 依赖 MySQL 的 SAVEPOINT 机制实现部分回滚。
  • MySQL 的事务隔离级别(如 READ COMMITTEDREPEATABLE READ)会影响事务间的可见性,间接影响 Spring 传播行为的最终效果(例如,REQUIRES_NEW 新建的事务能否读取到原事务未提交的数据,取决于隔离级别)。

三、核心区别与联系

维度

Spring 事务传播行为

MySQL 事务相关机制

层面

应用层(代码/框架层面),控制方法间事务交互

数据库层(存储引擎层面),控制事务的底层执行

核心目标

定义“事务方法调用时的规则”(如是否共用事务)

定义“事务的原子性、隔离性”等底层实现机制

依赖关系

依赖 MySQL 等数据库的事务支持(如 SAVEPOINT

为 Spring 传播行为提供底层能力支撑

典型场景

方法 A 调用方法 B 时的事务关系

存储过程中事务的嵌套执行、SAVEPOINT 控制

总结:Spring 的事务传播行为是应用层的事务交互规则,而 MySQL 的事务机制是数据库层的底层支撑,两者配合实现复杂的事务控制逻辑(例如,Spring 的 NESTED 依赖 MySQL 的 SAVEPOINTREQUIRES_NEW 依赖 MySQL 的事务独立性)。


网站公告

今日签到

点亮在社区的每一天
去签到