声明式事务(@Transactional)使用时需要注意的坑

 前言

 上两篇文章已经详细分析了申明式事务的实现原理,知道了底层原理之后,现在就可以开始使用申明式事务去简化我们的代码了。但是在使用@Transactional注解的时候也会经常遇到一些问题,有些问题不仔细测试观察的话还不容易发现,比如:事务失效,部分数据回滚,导致数据不一致等。这篇文章就来列一下使用@Transactional注解时应该注意哪些问题。


一、@Transactional事务不生效的各种场景

1.1 在同一个类中,有两个添加了@Transactional注解的方法A和B,A方法调用B方法,B方法事务不生效

  原因是A方法上面添加了事务的注解,所以是通过AOP生成的代理对象去调用被增强之后的方法,但是方法A调用同一个类中的另外一个添加了注解的B方法则是通过当前对象,也就是this去调用的,this并不是增强过后的代理对象,所以没有被AOP添加事务增强。同理其他的注解也是这样,这种情况也是会导致B方法上面的注解失效,如@Async等。

1.2 在非public方法上面添加@Transactional注解

  由于注解是基于AOP动态代理生成代理对象调用增强方法的,如果方法为非public的方法,则无法通过动态代理调用方法和增强方法。

1.3 注解中配置了rollbackFor熟性,但是抛出的异常并不是所配置的属性

@Transactional注解的rollbackFor默认是RuntimeException才会进行回滚,所以当方法抛出Exception的时候是不会触发事务的回滚的。

这个方法并不会让事务回滚,因为这里抛出的是Exception,事务默认是RuntimeException才会进行回滚。所以可以改成@Transactional(rollbackFor = Exception.class)

1.4 数据库引擎设置成了MyISAM

MyISAM引擎是一个适合查询的数据库引擎,它是不支持事务和索引的,所以当引擎为MyISAM的时候,事务是不生效的

1.5 在方法中使用了try catch将异常捕获了

如果方法中使用了try catch捕获了异常,而且异常并没有抛出来,则事务也不会进行回滚

1.6 多线程操作事务

如果主线程需要先执行一些修改数据库的操作,当子线程在进行处理出现异常时,主线程修改的数据则不会回滚。因为需要事务生效前提是操作的是同一个数据库的connect,而多线程的情况下,操作的都不是同一个connect,所以会导致事务不生效。

1.7 使用了特殊的事务传播特性

比如在使用PROPAGATION_REQUIRES_NEWPROPAGATION_NESTED传播特性之后,在子事务回滚之后父事务是不会回滚的,所以这就可能造成事务没生效的误解。在使用传播特性的时候一定要了解各种传播特性的作用。引入大佬文章《Spring事务的传播特性和隔离级别

二、申明式事务的其他特性

2.1 @Transactional添加readOnly = true提高只读方法的性能

@Transactional(readOnly=true) 真的是提高性能的灵丹妙药吗?

文章大概总结了@Transactional添加readOnly = true属性可以提高只读方法的性能的原理

  • 性能改进:只读实体不进行脏检查

  • 节省内存:不维护持久状态的快照

  • 数据一致性:只读实体的更改不会持久化

  • 当我们使用主从或读写副本集(或集群)时,@Transactional(readOnly = true)使我们能够连接到只读数据库

但是在日常开发中,我们是不会在一个只读方法上添加@Transactional注解的,但是需要注意的是,当一个非只读方法上面有@Transactional注解,而这个方法调用了只读方法,只读方法也会被事务增强,这个场景才需要在只读方法上添加@Transactional(readOnly=true)

2.2 多线程事务怎么回滚

支付宝一面:多线程事务怎么回滚?说用 @Transactional 可以回去等通知了!

2.3 事务的隔离级别相关

MYSQL事务的隔离性之MVCC


总结

本文主要是总结神秘式事务 @Transactional在使用需要我们去注意的问题,正确的使用事务是在日常开发中所必须具备的技能,不然可能会造成数据的不准备等问题。所以在使用事务的时候必须先全面的理解它,才能够使用好它。如果有需要补充的,感谢提供宝贵的意见

  • 17
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值