spring事物传播机制和隔离级别

本文探讨了在并发环境下,事务运行可能遇到的脏读、不可重复读和幻读问题,并详细介绍了Spring中的四种事务隔离级别,以及如何防止这些问题的发生。此外,文章还阐述了Spring的七种事务传播机制,包括其各自的行为和适用场景。

事物并发运行可以造成的问题

1.脏读  读取到另一个事物修改但还未提交的数据

2.不可重复读   是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。(即不能读到相同的数据内容)
例如,一个编辑人员两次读取同一文档,但在两次读取之间,作者重写了该文档。当编辑人员第二次读取文档时,文档已更改。原始读取不可重复。如果只有在作者全部完成编写后编辑人员才可以读取文档,则可以避免该问题。

3.幻读 一个事物读取几行记录后  另一个事物操作了数据  ,在后来的查询中第一个事务就会发现有些原来没有的记录。

(例如第一个事务对一个表中的数据进行了修改,比如这种修改涉及到表中的“全部数据行”。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入“一行新数据”。那么,以后就会发生操作第一个事务的用户发现表中还存在没有修改的数据行,就好象发生了幻觉一样)

 

事物隔离级别

1、读未提交(READ_UNCOMMITED):允许读取还未提交的改变了的数据。可能导致脏读、幻读、不可重复读。

2、读已提交(READ_COMMITED):允许在并发事务已经提交后读取。可防止脏读,但幻读、不可重复读仍可能发生。

3、可重复读(REPEATABLE_READ):对相同字段的多次读取是一致的,除非数据被事务本身改变。可防止脏读、不可重复读。但幻读仍可能发生。

4、可串行化(SERIALIZABLE):完全服从ACID的隔离级别,确保不发生脏读、幻读和不可重复读。他在所有的隔离级别中是最慢的,因为要完全锁住在事务中涉及的数据表。

5、Default:使用了后端数据库默认的隔离级别(spring中的选择项,也是isolation属性的默认值,Mysql默认采用REPEATABLE_READ隔离级别,Oracle默认采用READ_COMMITED隔离级别)。

事物传播机制 spring有7总种传播机制

1、PROPAGATION_REQUIRED:支持当前事务,如果当前不存在事务则新建一个。

2、PROPAGATION_SUPPORTS:支持当前事务,如果不存在,就不使用事务。

3、PROPAGATION_MANDATORY:支持当前事务,如果不存在,则抛出异常。

4、PROPAGATION_REQUIRES_NEW:如果当前有事务存在,挂起当前事务,创建一个新的事务。

5、PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果当前有事务存在,挂起当前事务。

6、PROPAGATION_NEVER:以非事务方式运行,如果当前有事务存在,抛出异常。

7、PROPAGATION_NESTED:如果当前存在一个事务,则该方法运行在一个嵌套的事务中。被嵌套的事务可以从当前事务中单独的提交和回滚。如果当前不存在事务,则开始一个新的事务。各厂商对这种传播行为的支持参差不齐,使用时需注意。
 

spring隔离级别和事物传播机制配置

<tx:advice id="txAdvice" transaction-manager="transactionManager">
     <tx:attributes>
          <tx:method name="query*" read-only="true" propagation="SUPPORTS" />
          <tx:method name="get*" read-only="true" propagation="SUPPORTS" />
          <tx:method name="insert*" propagation="REQUIRED" />
          <tx:method name="save*" propagation="REQUIRED" />
          <tx:method name="update*" propagation="REQUIRED" />
          <tx:method name="remove*" propagation="REQUIRED" />
          <tx:method name="delete*"  propagation="REQUIRED" />
     </tx:attributes>
</tx:advice>
由于没有给method配置isolation属性,所以默认是isolation=‘DEFAULT’,也就是使用后端数据库默认的隔离级别。

 


 

<think>嗯,用户这次想了解Spring事务传播机制隔离级别的详细解释。之前用户提到了线性表,但那已经是另一个话题了,现在需要专注在Spring事务上。用户可能正在开发企业级Java应用,遇到了事务管理的问题。从ta特意要求“详细解释”来看,应该不是初学者,可能是想深入理解原理来解决实际项目中的事务问题。之前提供的两个技术引用很有价值,特别是PlatformTransactionManager接口XML配置示例。关于传播行为,需要讲清楚七种类型的区别,特别是PROPAGATION_REQUIREDPROPAGATION_REQUIRES_NEW这种容易混淆的。隔离级别部分要强调脏读、不可重复读、幻读的具体表现,以及不同隔离级别的适用场景。注意到用户提供的引用里提到事务配置方式,所以在回答中需要区分注解配置XML配置的不同语法。还要解释清楚核心接口PlatformTransactionManagerTransactionDefinition的关系。对于传播机制,准备用场景对话的方式来说明每种行为的使用时机。比如PROPAGATION_SUPPORTS适合查询方法,PROPAGATION_MANDATORY用于必须存在事务的场景等。隔离级别部分考虑用表格对比,但也要说明Spring的默认隔离级别是数据库决定的这个重要知识点。脏读、不可重复读、幻读这些概念需要具体化,最好举例说明。最后的相关问题设计要针对可能产生的疑问,比如嵌套事务异常处理、隔离级别性能影响等实用话题。这样用户可以根据需要进一步探索。</think> ### Spring 事务传播机制详解 Spring 事务传播行为定义了**多个事务方法相互调用时事务如何传播**,由`Propagation`枚举类(实现`TransactionDefinition`接口)定义。以下是所有传播行为及其场景说明: | **传播行为类型** | **枚举值** | **行为描述** | **典型场景** | |----------------------------|---------------------------|-----------------------------------------------------------------------------|-----------------------------------------------------------------------------| | **必需事务** | `REQUIRED`(默认) | 若当前无事务则开启新事务;若存在事务则加入 | 大多数写操作(如订单创建)[^1] | | **支持事务** | `SUPPORTS` | 存在事务则加入;否则以非事务运行 | 查询操作(可兼容事务环境)[^2] | | **强制要求事务** | `MANDATORY` | 必须在事务中运行,否则抛出异常 | 金额结算(必须与其他操作同事务)[^1] | | **新建事务** | `REQUIRES_NEW` | 无论当前有无事务,都开启独立新事务(挂起原事务) | 日志记录(需独立提交)[^1] | | **非事务运行** | `NOT_SUPPORTED` | 以非事务方式执行,挂起当前事务 | 外部接口调用(不受事务管理) | | **禁止事务** | `NEVER` | 必须在非事务环境运行,否则抛出异常 | 静态数据加载 | | **嵌套事务** | `NESTED` | 当前有事务时创建嵌套子事务(可独立回滚);无事务时行为同`REQUIRED` | 批量处理子任务(允许部分失败回滚)[^1] | --- ### Spring 事务隔离级别详解 事务隔离级别解决**并发操作导致的数据一致性问题**,由`Isolation`枚举类定义。Spring 支持以下五级隔离: | **隔离级别** | **枚举值** | **脏读** | **不可重复读** | **幻读** | **实现基础** | |----------------------------|-----------------------------|----------|----------------|----------|------------------------------| | **默认隔离级** | `DEFAULT` | ❌ | ❌ | ❌ | 使用数据库默认级别 | | **读未提交** | `READ_UNCOMMITTED` | ✔️ | ✔️ | ✔️ | 最低隔离性,高并发性能 | | **读已提交** | `READ_COMMITTED`(常用) | ❌ | ✔️ | ✔️ | Oracle/SQL Server 默认 | | **可重复读** | `REPEATABLE_READ` | ❌ | ❌ | ✔️ | MySQL 默认 | | **串行化** | `SERIALIZABLE` | ❌ | ❌ | ❌ | 最高隔离性,低并发性能 | #### 关键概念说明 1. **脏读(Dirty Read)** 读取到其他事务未提交的数据(如事务A修改数据未提交,事务B读到修改值后A又回滚)。 2. **不可重复读(Non-Repeatable Read)** 同一事务内多次读取结果不同(如事务A两次读取间事务B修改并提交了数据)。 3. **幻读(Phantom Read)** 同一查询返回不同行数(如事务A统计用户数时事务B新增用户并提交)。 --- ### 配置示例 #### 1. 注解声明事务(推荐) ```java @Transactional( propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class ) public void createOrder(Order order) { // 业务逻辑 } ``` #### 2. XML 配置事务管理器(兼容旧系统) ```xml <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="create*" propagation="REQUIRED" isolation="READ_COMMITTED"/> </tx:attributes> </tx:advice> ``` --- ### 事务关键接口说明 ```java public interface PlatformTransactionManager { // 获取事务状态(根据定义) TransactionStatus getTransaction(TransactionDefinition definition); // 提交事务 void commit(TransactionStatus status); // 回滚事务 void rollback(TransactionStatus status); } ``` > **`TransactionDefinition`** 定义了传播行为、隔离级别、超时时间等核心属性[^1]。 --- ### 相关问题 1. **嵌套事务`NESTED`与新建事务`REQUIRES_NEW`有何本质区别?** (答:嵌套事务共享主事务连接,子事务回滚不触发主事务回滚;新建事务完全独立) 2. **为什么MySQL默认隔离级别是可重复读(`REPEATABLE_READ`)而Oracle是读已提交(`READ_COMMITTED`)?** (答:设计差异导致,MySQL通过间隙锁解决幻读问题) 3. **如何在`REQUIRED`传播行为下实现部分操作独立提交?** (答:将需独立提交的方法声明为`REQUIRES_NEW`) 4. **事务隔离级别选择如何影响系统并发性能?** (答:隔离级别越高(如串行化),锁竞争越激烈,并发性能越低) 5. **`@Transactional`注解在类内部方法调用为何失效?** (答:因Spring AOP代理机制限制,需通过代理对象调用)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值