Spring事务

本文详细介绍了事务的ACID特性,包括原子性、一致性、隔离性和持久性,并探讨了如何通过JDBC和Mybatis控制事务。重点讲述了Spring事务管理,包括AOP实现、传播属性和隔离级别。此外,还讨论了事务可能导致的问题如脏读、不可重复读和幻读及其解决方案,并分析了Spring的默认传播属性和只读、超时、回滚异常属性。最后,提到了事务失效的几种情况。
摘要由CSDN通过智能技术生成
1. 什么是事务?
保证业务操作完整性的一种数据库机制

事务的4个特点: A C I D
1. A 原子性
2. C 一致性
3. I 隔离性
4. D 持久性
2. 如何控制事务
JDBC:
	Connection.setAutoCommit(false);
	Connection.commit();
	Connection.rollback();
Mybatis:
	Mybatis自动开启事务
	sqlSession.commit();
	sqlSession.rollback();
sqlSerssion底层也是调用Connection.commit(),Connection.rollback()实现
结论:控制事务的底层,都是Connection对象完成的
3. Spring控制事务的开发
spring是通过AOP的方式进行事务开发
额外功能
spirng封装好的实现,事务实现都需要依赖Connection连接
1. org.springframework.jdbc.datasource.DataSourceTransactionManager
2. 注入连接池DataSource

具体实现
1. MethodInterceptor实现
   public Object invoke(MethodIncocation invocation) {
   		try {
   			Connection.setAutoCommit(false);
   			// 方法
   			Object ret = invocation.proceed();
   			Connection.commit();
   		}catch(Exception e) {
   			Connection.rollback();
   		}
   		return ret;
   }
2. @Aspect + @Around注解实现
切入点
@Transactional
1. 类上:类中所有方法都会加入事务
2. 方法上:该方法会加入事务
组装切面
1. 切入点
2. 额外功能

<tx:annotation-driven transaction-manager=""/>
4. 事务详解

##### 4.1 事务注解

@Transactional(isolation = ,propagation = ,readOnly = ,timeout = ,rollbackF or = ,noRollbackFor = )
4.2 参数详解
1. isolation - 隔离级别
        READ_UNCOMMITTED - 读事务未提交的数据
        READ_COMMITTED	 - 读事务提交的数据	
        REPEATABLE_READ  - 可重复读
        SERIALIZABLE	 - 序列化
2. propagation		- 传播
  	readOnly		- 只读
  	timeout			- 超时
  	rollbackFor		- 回滚
  	norollbackFor	- 不回滚
4.3 事务产生的问题
4.3.1 脏读
# 一个事务读取了另一个事务中没有提交的数据,会在本事务中产生数据不一致的问题
	解决方案:
		isolation = Isolation.READ_COMMITTED(事务隔离级别 = 读事务提交后)
4.3.2 不可重复读
示例:同一个数据,修改该数据事务未提交时被另一个事务查询了一次,事务提交后查询的事务又查询了一次,两次查询的结果不同,即不可重复读。
# 一个事务中,多次读取相同的数据,但是读取的结果不一样。会在本事务中产生数据不一致的问题
	解决方案
		isolation = Isolation.REPEATABLE_READ(事务隔离级别 = 可重复读)
本质:行锁
4.3.3 幻读
示例:一个事务中对表数据余额进行了求和统计查询,另一个事务对该表插入了一条余额不为0的新数据并提交了事务,当查询的事务再次统计查询值时,求和的结果则会变化。即幻读
# 一个事务中,多次对整表进行查询统计,但结果不一样,会在本事务中产生数据不一致的问题
	解决方案
		isolation = Isolation.SERIALIZABLE(事务隔离级别 = 序列化)
本质:表锁
4.4 传播属性
4.4.1 传播属性的概念
概念:描述了事务解决嵌套问题的特征

示例:事务A包含事务B和事务C,当事务B完成提交,事务C执行时发生回滚,此时B已经提交不能再回滚,导致A事务丧失原子性
产生的问题:大事务中融入了多个小事务,彼此会产生影响,最终导致外部大的事务丧失了事务的原子性
4.4.2 传播属性的值及用法
传播属性值外部不存在事务外部存在事务用法
REQUIRED开启新的事务融合到外部事务中propagation=Propagation.REQUIRED
SUPPORTS不开启新的事务融合到外部事务中propagation=Propagation.SUPPORTS
REQUIRES_NEW不开启新的事务挂起外部事务,创建新的事务propagation=Propagation.REQUIRES_NEW
NOT_SUPPORTED不开启新的事务挂起外部事务propagation=Propagation.NOT_SUPPORTED
NEVER不开启新的事务抛出异常propagation=Propagation.NEVER
MANDATORY抛出异常融合到外部事务中propagation=Propagation.MANDATORY
4.4.3 传播属性示例
  • REQUIRED(适合增删改方法)
    1. a方法外部不存在事务,REQUIRED就开启当前a的新事务
    @Transactional(propagation=Propagation.REQUIRED)
    aMethod {
    	2. b方法外部存在a事务,则融合到a事务中
    	@Transactional(propagation=Propagation.REQUIRED)
    	bMethod {
    	
    	}
    	
    	3. c方法外部存在a事务,则融合到a事务中
        @Transactional(propagation=Propagation.REQUIRED)
    	cMethod {
    	
    	}
    }
    # 结论:相当于将3个方法合并,并给方法开始结尾加上事务,3个方法同时符合原子性。
    
  • SUPPORTS(适合查询方法)
    1. a方法外部不存在事务,SUPPORTS也就不开启事务。相当于a方法无事务
    @Transactional(propagation=Propagation.SUPPORTS)
    aMethod {
    
    }
    
    2. b方法外部不存在事务,REQUIRED就开启当前b的新事务
    @Transactional(propagation=Propagation.REQUIRED)
    bMethod {
    	3. c方法外部存在b事务,SUPPORTS则融合到b事务中
        @Transactional(propagation=Propagation.SUPPORTS)
    	cMethod {
    	
    	}
    }
    结论:有则融合,无则没作用
    
  • REQUIRES_NEW(适合不能让事务融合的方法)
    场景:日志。业务方法开启事务,去调用了开启事务的日志方法。这种情况,不能让日志方法的事务融合到外部业务方法中。因为,业务方法回滚会导致日志也回滚,而日志需要记录操作,不能回滚。
    1. b方法外部不存在事务,REQUIRED就开启当前b的新事务
    @Transactional(propagation=Propagation.REQUIRED)
    bMethod {
    	2. log方法外部存在b事务,REQUIRES_NEW则将b事务暂停,log方法事务执行完再通知b事务执行
        @Transactional(propagation=Propagation.REQUIRES_NEW)
    	log {
    	
    	}
    }
    
4.4.4 Spring的默认传播属性
REQUIRED是传播属性的默认值,即不指定propagation时
增删改方法:采用默认值
查询方法:显示的指定传播属性为SUPPORTS
4.5 只读属性
默认值false
针对于只进行查询操作的业务方法,可以加入只读属性,提高运行效率。本质是不加锁
4.6 超时属性
指定了事务的最大等待时间
1. 当前事务访问数据库时,有可能访问的数据行或表被别的事务进行了加锁,那么此时当前事务就必须进行等待
2. 等待时间单位:秒
3. @Transactional(timeout = 2),当前事务最多等待2秒,超时抛出异常TransactionTimeOutException
4. 超时时间默认值:-1.即由当前访问的数据库来决定超时时间
4.7 回滚异常属性
1. Spring事务处理默认对RuntimeException及其子类异常进行回滚
2. Spring事务处理默认对非RuntimeException的Exception及其子类异常采用的是提交
3. @Transactional(rollbackFor = {Exception.class}),指定回滚异常
4. @Transactional(noRollbackFor = {Exception.class}),指定不回滚异常
4.8 隔离属性
4.8.1 隔离级别比较
并发安全:SERIALIZABLE > REPEATABLE_READ > READ_COMMITTED
运行效率:READ_COMMITTED > REPEATABLE_READ > SERIALIZABLE
隔离级别MYSQLORACLE
READ_COMMITTED
REPEATABLE_READ×
SERIALIZABLE
4.8.2 默认隔离属性
isolation = Isolation.DEFAULT 会调用不通数据库所设置的默认隔离属性
Mysql: REPEATABLE_READ
Oracle:READ_COMMITTED
数据库查询默认隔离属性
Mysql:select @@tx_isolation;
Oracle:Select s.sid,s.serial#,CASE BITAND(t.flag,POWER(2,28))
	
5. 事务失效
5.1 同一个类中的方法调用
1. a方法开启事务,a内部调用未开启事务的b方法。b会融合进a的事务中,也具有事务特性。符合原子性
		a方法中不论调用多少个未开启事务的方法,都会融合进a的事务
2. a方法开启事务,a内部调用未开启事务的b方法。b内部又调用未开启事务的c方法,b、c都会融合进a的事务中,也都具有事务特性。符合原子性
5.2 不同类中的方法调用

​ 持续更新中

5.3 不同服务同是数据库间方法的调用
5.4 不同服务且不同数据库方法的调用
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值