前言
如果您觉得有用的话,记得给博主点个赞,评论,收藏一键三连啊,写作不易啊^ _ ^。
而且听说点赞的人每天的运气都不会太差,实在白嫖的话,那欢迎常来啊!!!
事务的大千世界(声明式事务、编辑式事务、分布式事务)
1、声明式事务
概述::
Spring 支持声明式事务,使用@Transactional注解在方法上表明该方法需要事务支持,spring Boot自动开启对声明式事务的支持,从原理上这是基于注解式AOP的实现,被注解的方法在被调用时,spring开启一个新的事务,当方法无异常运行结束后,提交事务,@Transactional注解也可以注解在类上,表示该类所有的public方法都开始事务支持。
1.1、@Transactional作用域
@Transactional 可以作用在接口、类、类方法
1)、作用于类:
当把@Transactional 注解放在类上时,表示所有该类的public方法都配置相同的事务属性信息。
2)、作用于方法:
当类配置了@Transactional,方法也配置了@Transactional,方法的事务会覆盖类的事务配置信息。
3)、作用于接口:
不推荐这种使用方法,因为一旦标注在Interface上并且配置了Spring AOP 使用CGLib动态代理,将会导致@Transactional注解失效
1.2、@Transactional用法
属性列表:
序号 | 属性 | 含义 |
---|---|---|
1 | propagation属性 | 代表事务的传播行为 |
2 | isolation 属性 | 事务的隔离级别 |
3 | timeout 属性 | 事务的超时时间 |
4 | readOnly 属性 | 指定事务是否为只读事务 |
5 | rollbackFor 属性 | 用于指定能够触发事务回滚的异常类型,可以指定多个异常类型。 |
6 | noRollbackFor属性 | 该属性用于设置不需要进行回滚的异常类,抛出指定的异常类型,不回滚事务,也可以指定多个异常类型 |
详情:
1.2.1、propagation属性
propagation 代表事务的传播行为,默认值为 Propagation.REQUIRED,其他的属性信息如下:
Propagation.REQUIRED:
如果当前存在事务,则加入该事务,如果当前不存在事务,则创建一个新的事务。
Propagation.SUPPORTS:
支持当前事务,若无事务则不用事务
Propagation.MANDATORY:
强制方法在事务中执行,若无事务则抛出异常。
Propagation.REQUIRES_NEW:
无论是否存在事务,都创建一个新的事务,原来的挂起,新的执行完毕,继续执行老的事务
Propagation.NOT_SUPPORTED:
以非事务的方式运行,如果当前存在事务,暂停当前的事务。
Propagation.NEVER:
以非事务的方式运行,如果当前存在事务,则抛出异常。
Propagation.NESTED :
如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作
1.2.2、isolation 属性
isolation :事务的隔离级别,默认值为Isolation.DEFAULT
该属性用于设置底层数据库的事务隔离级别,事务隔离级别用于处理多事务并发情况,通常使用数据库的默认隔离级别即可
solation.DEFAULT:
使用底层数据库默认的隔离级别。
Isolation.READ_UNCOMMITTED:
A事务修改一条记录但没有提交事务,在B事务可以读取到修改后的记录,不能防止脏读、不可重复读和幻读。
Isolation.READ_COMMITTED:
只有A事务修改一条记录并提交事务,B事务才可以读取到A事务修改后的数据,防止脏读、不可重复读和幻读。
Isolation.REPEATABLE_READ:
不仅仅能实现【Isolation.READ_COMMITTED】的功能,并且当A事务读取一条记录,B事务将不允许修改这条记录,防止脏读和不可重复读,但不防止幻读。
Isolation.SERIALIZABLE:
最可靠的事务隔离级别,此级别下的事务是顺序执行的,可防止脏读、不可重复读和幻读,但开销大。
1.2.3、timeout 属性
timeout :事务的超时时间,默认值为 -1。如果超过该时间限制但事务还没有完成,则自动回滚事务。【int整形】
1.2.4、readOnly 属性
readOnly :指定事务是否为只读事务,默认值为 false;为了忽略那些不需要事务的方法,比如读取数据,可以设置 read-only 为 true。
1.2.5、rollbackFor 属性
rollbackFor :用于指定能够触发事务回滚的异常类型,可以指定多个异常类型。
1.2.6、noRollbackFor属性
noRollbackFor:
该属性用于设置不需要进行回滚的异常类,抛出指定的异常类型,不回滚事务,也可以指定多个异常类型
1.3、@Transactional失效场景
列表:
序号 | 失效场景 |
---|---|
1 | @Transactional 应用在非 public 修饰的方法上 |
2 | @Transactional 注解属性 propagation 设置错误 |
3 | @Transactional 注解属性 rollbackFor 设置错误 |
4 | 同一个类中方法调用,导致@Transactional失效 |
5 | 异常被你的 catch“吃了”导致@Transactional失效 |
6 | 数据库引擎不支持事务 |
7 | @Transactional注解用在接口上,并且配置Spring AOP 使用CGLib动态代理 |
2、自定义编辑式事务
简单来说利用切面拦截的方式来制作自定义事务:
即:
- 执行方法前开启事务
- 执行方法
- 执行方法后提交事务或回滚事务
举例:
2.1、编辑式事务切面注解:
/**
* 编辑自定义事务控制注解
* @author yangzhenyu
* */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface TransactionalSelf {
}
2.2、编辑式事务切面注解实现:
/**
* 编辑自定义事务控制注解
* @author yangzhenyu
* */
@Aspect
@Component
@EnableAspectJAutoProxy(exposeProxy = true,proxyTargetClass = true)
public class TransactionalSelfAspect {
private static Logger log = LoggerFactory.getLogger(TransactionalSelfAspect.class);
@Pointcut("@annotation(com.yzy.demo.transactional.annotation.TransactionalSelf)")
public void pointcut(){
};
//事务处理类
@Autowired
private DataSourceTransactionManager manager;
/**事务切面处理方法
* */
@Around("pointcut()")
public Object cut(ProceedingJoinPoint point) throws Throwable{
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
//如果当前没有事务,就新建一个事务,如果已经存在事务,就加入当前事务
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); //事务传播行为
def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
TransactionStatus status = manager.getTransaction(def);
Object result = null;
try{
result = point.proceed();
//提交事务
manager.commit(status);
}catch (Exception e){
//回滚事务
manager.rollback(status);
log.error("==========================回滚事务=================================");
}
return result;
}
}
3、分布式事务
3.1、什么是分布式事务,分布式事务应用场景:
前提:
1)、微服务架构
2)、库房应用服务和订单应用服务是两个独立的应用服务,并且有独立的数据存储。
业务场景:
当生成新的交易订单时,表示交易完成,交易完成后需扣除相应的库存,
什么是分布式事务:
此场景下,业务逻辑具有原子性,要么同时成功,要么同时失败,为了保证数据一致性,在这里就有分布式事务观念的产生了。
3.2、分布式事务的特性
1)一般事务的ACID特性
- 原子性
- 一致性
- 隔离性
- 持久性
2)分布式事务一般都拥有BASE特性
- 基本可用
- 柔性状态
- 最终一致性
总结:出于性能考虑,分布式架构下,分布式事务难以采用强一致性事务方案,只能最求柔性状态、最终一致性,因此分布式事务框架也称柔性事务框架