Spring Transaction

本文深入解析Spring中的事务管理机制,包括基于PlatformTransactionManager的局部事务管理策略,详细介绍了不同事务传播行为下的事务状态变化,如PROPAGATION_REQUIRED、PROPAGATION_REQUIRE_NEW等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Spring的局部事务管理策略是基于PlatformTransactionManager(PTM)的, 这个接口比较单纯, 只有如下三个方法.
    TransactionStatus getTransaction(TransactionDefinition definition) throws  TransactionException;
    void commit(TransactionStatus status) throws TransactionException;
    void rollback(TransactionStatus status) throws TransactionException;

    设想有个Service(A), 它采用声明式事务, 事务传播行为是PROPAGATION_REQUIRED. 同时使用DataSourceTransactionManager(DTM)作为事务管理器. 那么在调用Service(A)之前, TransactionInterceptor会构造TransactionInfo(A), 并把它绑定到当前线程上, 同时调用DTM.getTransaction方法, 以下是DTM.getTransaction方法调用完毕后一种可能的事务状态.
TransactionInfo(A)
  |->oldTransactionInfo = null
  |->TransactionStatus(A)
         |->newTransaction=true
         |->savepoint=null
         |->DataSourceTransactionObject(A)
                |->newConnectionHolder=true
                |->SuspendedResourcesHolder(A)
                |      |->suspendedResources=null
                |->ConnectionHolder(A)
                       |->connectionHandle=SimpleConnectionHandle(dataSource.getConnection())
                       |->transactionActive=true

    假设在Service(A)中调用了Service(B), 它的事务传播行为也是PROPAGATION_REQUIRED. 以下是为Service(B)调用了DTM.getTransaction方法后一种可能的事务状态.
TransactionInfo(B)
  |->oldTransactionInfo=TransactionInfo(A)
  |->TransactionStatus(B)
         |->newTransaction=false
         |->savepoint=null
         |->DataSourceTransactionObject(B)
                |->newConnectionHolder=false
                |->SuspendedResourcesHolder(B)
                |      |->suspendedResources=null
                |->ConnectionHolder(A)
    TransactionInfo(A)和TransactionInfo(B)是绑定到当前线程的, 而且从以上两个状态描述中可以看出来, TransactionInfo采用了单向链表结构, 表头永远是当前堆栈栈顶的方法对应的TransactionInfo对象. 由于Service(A)和Service(B)的事务传播行为都是PROPAGATION_REQUIRED, 所以TransactionStatus(B)的newTransaction属性是false, 也就是在对Service(B)的调用中并没有开启新的事务. 同时DataSourceTransactionObject(B)的ConnectionHolder引用是指向ConnectionHolder(A)的, 也就是说在Service(B)中将和Service(A)使用同一个JDBC连接.

    假设在Service(A)中调用了Service(B), 它的事务传播行为是PROPAGATION_REQUIRE_NEW. 以下是为Service(B)调用了DTM.getTransaction方法后一种可能的事务状态.
TransactionInfo(B)
  |->oldTransactionInfo=TransactionInfo(A)
  |->TransactionStatus(B)
         |->newTransaction=true
         |->savepoint=null
         |->DataSourceTransactionObject(B)
                |->newConnectionHolder=true
                |->SuspendedResourcesHolder(B)
                |      |->suspendedResources=ConnectionHolder(A)
                |->ConnectionHolder(B)
                       |->connectionHandle=SimpleConnectionHandle(dataSource.getConnection())
                       |->transactionActive=true
    由于Service(B)的事务传播行为是PROPAGATION_REQUIRE_NEW, 那么Service(A)的事务将被挂起, 在SuspendedResourcesHolder(B)的suspendedResources属性中保存了被挂起的ConnectionHolder(A). ConnectionHolder(B)也不再指向ConnectionHolder(A), 而是获得一个新的JDBC连接, 同时DTM会把ConnectionHolder(B)绑定到当前线程上. 这意味着Service(B)的事务会在一个不同于Service(A)的JDBC连接中进行. 直到Service(B)方法执行完毕后, DTM会把ConnectionHolder(A)重新绑定到当前线程上, 也就是说接下来的Service(A)方法中仍然会使用ConnectionHolder(A)中保存的JDBC连接.

    如果Service(B)的事务传播行为是PROPAGATION_NOT_SUPPORTED, 那么Service(A)的事务将被挂起, 同时DTM会解除当前线程上ConnectionHolder(A)的绑定. 但是并不会获得一个新的JDBC连接(因为不需要为ServiceB开启事务, 同时TransactionStatus(B)的newTransaction属性是false). 但是如果在Service(B)中使用了DataSourceUtils.getConnection()方法, 那么在Service(B)中会获得一个新的JDBC连接, 并绑定一个新的ConnectionHolder到当前线程上.

    如果Service(B)的事务传播行为是PROPAGATION_NESTED, 那么会开启一个嵌套事务. 首先引用一下Juergen Hoeller关于嵌套事务的描述:
PROPAGATION_NESTED on the other hand starts a "nested" transaction, which is a true subtransaction of the existing one. What will happen is that a savepoint will be taken at the start of the nested transaction. íf the nested transaction fails, we will roll back to that savepoint. The nested transaction is part of of the outer transaction, so it will only be committed at the end of of the outer transaction.
Nested transactions essentially allow to try some execution subpaths as subtransactions: rolling back to the state at the beginning of the failed subpath, continuing with another subpath or with the main execution path there - all within one isolated transaction, and not losing any previous work done within the outer transaction.
    也就是说, 嵌套事务和外层事务使用的是同一个JDBC连接上的事务, 嵌套事务伴随着外层事务的提交而提交, 如果嵌套事务rollback, 那么嵌套事务会回滚到嵌套事务开启时的Save Point处, 而外层事务不受影响. 因此嵌套事务需要支持JDBC 3.0 Save Point特性的数据库以及JDBC驱动程序(用con.getMetaData().supportsSavepoints()判断, MySql5.1支持). 以下是为Service(B)调用了DTM.getTransaction方法调用完毕后相关的事务状态. 其中TransactionStatus(B)的savepoint属性保存了con.setSavepoint()返回的Savepoint对象.
TransactionInfo(B)
  |->oldTransactionInfo=TransactionInfo(A)
  |->TransactionStatus(B)
         |->newTransaction=false
         |->savepoint=Savepoint(B)
         |->DataSourceTransactionObject(B)
                |->newConnectionHolder=false
                |->SuspendedResourcesHolder(B)
                |      |->suspendedResources=null
                |->ConnectionHolder(A)

 

内容概要:本文档为《400_IB Specification Vol 2-Release-2.0-Final-2025-07-31.pdf》,主要描述了InfiniBand架构2.0版本的物理层规范。文档详细规定了链路初始化、配置与训练流程,包括但不限于传输序列(TS1、TS2、TS3)、链路去偏斜、波特率、前向纠错(FEC)支持、链路速度协商及扩展速度选项等。此外,还介绍了链路状态机的不同状态(如禁用、轮询、配置等),以及各状态下应遵循的规则和命令。针对不同数据速率(从SDR到XDR)的链路格式化规则也有详细说明,确保数据包格式和控制符号在多条物理通道上的一致性和正确性。文档还涵盖了链路性能监控和错误检测机制。 适用人群:适用于从事网络硬件设计、开发及维护的技术人员,尤其是那些需要深入了解InfiniBand物理层细节的专业人士。 使用场景及目标:① 设计和实现支持多种数据速率和编码方式的InfiniBand设备;② 开发链路初始化和训练算法,确保链路两端设备能够正确配置并优化通信质量;③ 实现链路性能监控和错误检测,提高系统的可靠性和稳定性。 其他说明:本文档属于InfiniBand贸易协会所有,为专有信息,仅供内部参考和技术交流使用。文档内容详尽,对于理解和实施InfiniBand接口具有重要指导意义。读者应结合相关背景资料进行学习,以确保正确理解和应用规范中的各项技术要求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值