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

浙公网安备 33010602011771号