Spring中的事务传播行为

在Spring中,事务的传播行为大致分为三类:融合、挂起、嵌套。
以下的事务描述都是基于mysql,其他数据库不考虑。
融合:当A方法调用B方法,这两个方法都添加了@Transactional,如果A方法有事务,那么B事务会融入到A的事务中。

BEGIN:
	UPDATE yyyy:
	  -----两个事务的分界线----------
			update xxxx:
	  ---------------
	  update zzz:
commit;

PROPAGATION_REQUIRED 当前环境存在事务,用当前环境的事务,没有就新启动一个事务。
PROPAGATION_SUPPORTS 不管当前环境是否有事务,都会新启动一个事务。
PROPAGATION_MANDATORY 当前环境必须运行在事务的环境,如果没有就报错。
挂起:当A方法调用B方法,当前线程的ThreadLocal会将之前的连接暂存起来,从连接池中重新拿一个连接,执行B方法,B方法执行完毕后,ThreadLocal再拿挂起的连接继续执行A方法。
应用场景:A方法报错不要影响B方法,或者B方法报错不要影响A方法。

BEGIN:
	UPDATE yyyy
	---两个事务的分界线---------
		begin:
		update xxxx;
	---------------
	update zzzz;
commit;

PROPAGATION_REQUIRES_NEW 标识当前事务必须运行在自己的事务中,一个新的事务会被启动,如果当前环境存在事务,就挂起事务。新的事务执行完毕之后,挂起的事务继续运行。
PROPAGATION_NOT_SUPPORTED 表示当前环境不支持事务,如果当前环境存在事务,就挂起事务,方法执行完毕后,挂起的事务继续运行。
PROPAGATION_NEVER 表示该方法不能运行在事务中,如果当前环境存在事务就报错。
嵌套:mysql是不支持嵌套事务的,Spring的做法很聪明,模拟了一个嵌套事务。

begin:
	update user set money = 100 where id = 1;
	SAVEPOINT a:
	 update user set money = 100 where id = 3;
	 update user set money = 100 where id = 4;
	 --以上的代码有问题则回滚到保存点
	 ROLLBACK to a;
	 --后边的事务不会受影响
	 update user set money = 100 where id = 5;
commit;

PROPAGATION_NESTED 如果当前环境存在事务,就会嵌套在该事务中运行,嵌套的事务可以独立运行在当前事务单独的运行和回滚。不存在,就会新启动一个事务,嵌套在新启动的事务中运行。
关于事务传播行为的相关视频:https://www.bilibili.com/video/BV1R8411c7m2/?spm_id_from=333.337.search-card.all.click&vd_source=73d100dec9413b936c0d6dc4e24a1168

posted @ 2025-07-03 09:14  Charlie-Pang  阅读(12)  评论(0)    收藏  举报