慎用事务序列化,事务嵌套不支持事务序列化

springboot+springcloud分服务架构中,使用同一MySQL数据库的不同服务之前,
当主接口采用@Transactional(rollbackFor = Exception.class,isolation = Isolation.SERIALIZABLE)注解事务时,分接口,即主接口调用其他分服务接口时不能采用事务回滚注解,否则将会导致事务嵌套,从而造成死锁(死锁查询select * from information_schema.innodb_trx)

isolation = Isolation.SERIALIZABLE序列化事务不支持事务嵌套

所以,主接口慎用注解序列化事务,事务嵌套时一般采用普通事务就可以,而分接口也可标记为新事务

@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRES_NEW)

报错信息为事务嵌套失败导致

org.springframework.dao.CannotAcquireLockException:
### Error updating database.  Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction
### The error may involve com.yundianba.dao.UseCouponDao.updateByPrimaryKey-Inline
### The error occurred while setting parameters
### SQL: update user_coupon   SET MEMBER_ID = ?,OBTAIN_TIME = now(),     USE_TYPE = ?,USE_TIME =now(),   ORDER_CODE = ?   where 1=1      and COUPON_CODE = ?
### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction
; ]; Lock wait timeout exceeded; try restarting transaction; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction

一、readOnly读写事务控制

readOnly=true表明所注解的方法或类只是读取数据。

readOnly=false表明所注解的方法或类是增加,删除,修改数据。

二、isolation事务隔离级别

我们在使用事务过程中,通常会发生以下三种情况:

1、脏读(dirty read):当一个事务读取另一个事务尚未提交的修改时,产生脏读。

2、不可重复读(non-repeatable read):同一查询在同一事务中多次进行,由于其他提交事务所做的修改或删除,每次返回不同的结果集,此时发生非重复读。

3、幻像读(phantom read):同一查询在同一事务中多次进行,由于其他提交事务所做的插入操作,每次返回不同的结果集,此时发生幻像读。

针对上述三种情况,Spring提供了5种事务隔离级别予以解决:

1、DEFAULT默认级别

DEFAULT为数据源(数据库)的默认隔离级别,以目前常用的MySQL为例,默认的隔离级别通常为REPEATABLE_READ。

2、READ_UNCOMMITTED未授权读取级别

这是最低的隔离级别,一个事务能读取到别的事务未提交的更新数据,很不安全,可能出现丢失更新、脏读、不可重复读、幻读。

3、READ_COMMITTED授权读取级别

以操作同一行数据为前提,读事务允许其他读事务和写事务,未提交的写事务禁止其他读事务和写事务。此隔离级别可以防止更新丢失、脏读,但不能防止不可重复读、幻读。此隔离级别可以通过“瞬间共享读锁”和“排他写锁”实现。

4、REPEATABLE_READ可重复读取级别

保证同一事务中先后执行的多次查询将返回同一结果,不受其他事务影响。以操作同一行数据为前提,读事务禁止其他写事务,但允许其他读事务,未提交的写事务禁止其他读事务和写事务。此隔离级别可以防止更新丢失、脏读、不可重复读,但不能防止幻读。

5、SERIALIZABLE序列化级别

所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰。提供严格的事务隔离,此隔离级别可以防止更新丢失、脏读、不可重复读、幻读。如果仅仅通过“行级锁”是无法实现事务序列化的,必须通过其他机制保证新插入的数据不会被刚执行查询操作的事务访问到。

隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大。对于多数应用程序,可以优先考虑把数据库系统的隔离级别设为Read Committed。它能够避免更新丢失、脏读,而且具有较好的并发性能。尽管它会导致不可重复读、幻读这些并发问题,在可能出现这类问题的个别场合,可以由应用程序采用悲观锁或乐观锁来控制。

三、Propagation事务传播行为

Propagation属性用来枚举事务的传播行为。所谓事务传播行为就是多个事务方法相互调用时,事务如何在这些方法间传播。Spring支持7种事务传播行为,默认为REQUIRED。

1、REQUIRED

REQUIRED是常用的事务传播行为,如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。

2、SUPPORTS

SUPPORTS表示当前方法不需要事务上下文,但是如果存在当前事务的话,那么这个方法会在这个事务中运行。

3、MANDATORY

MANDATORY表示该方法必须在事务中运行,如果当前事务不存在,则会抛出一个异常。不会主动开启一个事务。

4、REQUIRES_NEW

REQUIRES_NEW表示当前方法必须运行在它自己的事务中。一个新的事务将被启动,如果存在当前事务,在该方法执行期间,当前事务会被挂起(如果一个事务已经存在,则先将这个存在的事务挂起)。如果使用JTATransactionManager的话,则需要访问TransactionManager。

5、NOT_SUPPORTED

NOT_SUPPORTED表示该方法不应该运行在事务中,如果存在当前事务,在该方法运行期间,当前事务将被挂起。如果使用JTATransactionManager的话,则需要访问TransactionManager。

6、NEVER

NEVER表示当前方法不应该运行在事务上下文中,如果当前正有一个事务在运行,则会抛出异常。

7、NESTED

NESTED表示如果当前已经存在一个事务,那么该方法将会在嵌套事务中运行。嵌套的事务可以独立于当前事务进行单独地提交或回滚。如果当前事务不存在,那么其行为与REQUIRED一样。嵌套事务一个非常重要的概念就是内层事务依赖于外层事务。外层事务失败时,会回滚内层事务所做的动作。而内层事务操作失败并不会引起外层事务的回滚。

综上所述,NESTED和REQUIRES_NEW非常相似,都是开启一个属于它自己的新事务。使用REQUIRES_NEW时,内层事务与外层事务就像两个独立的事务一样,一旦内层事务进行了提交后,外层事务不能对其进行回滚。当内部事务开始执行时, 外部事务将被挂起, 内务事务结束时, 外部事务将继续执行。两个事务互不影响,两个事务不是一个真正的嵌套事务,同时它还需要JTA事务管理器的支持。

使用NESTED时,外层事务的回滚可以引起内层事务的回滚。而内层事务的异常并不会导致外层事务的回滚,它是一个真正的嵌套事务。嵌套事务开始执行时, 它将取得一个 savepoint,如果这个嵌套事务失败, 将回滚到此savepoint。潜套事务是外部事务的一部分, 只有外部事务结束后它才会被提交。

慎用事务序列化@Transactional(rollbackFor = Exception.class,isolation = Isolation.SERIALIZABLE)相关推荐

  1. java rollback_Spring中的@Transactional(rollbackFor = Exception.class)属性详解

    序言 今天我在写代码的时候,看到了.一个注解@Transactional(rollbackFor = Exception.class),今天就和大家分享一下,这个注解的用法: 异常 如下图所示,我们都 ...

  2. @Transactional(rollbackFor = Exception.class) 详解

    17.@Transactional(rollbackFor = Exception.class) 详解 1.参考来源:https://www.cnblogs.com/clwydjgs/p/931784 ...

  3. @Transactional(rollbackFor=Exception.class) 遇上try catch

    当@Transactional遇上try catch @Transactional(rollbackfor=Exception.class)--抛出Exception,执行回滚 但是如果被catch捕 ...

  4. Spring中的@Transactional(rollbackFor = Exception.class) try catch 异常时候 会失效

    在catch里加TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

  5. 为什么SpringBoot项目事务@Transactional(roolbackFor = {Exception.class})加rollbackFor

    一.@Transactional何时回滚 其实 @Transactional是spring的aop实现的典型,通过cglib的动态代理去实现的的编程模式, 这个是众所周知的. @Transaction ...

  6. 为什么阿里规定需要在事务注解 @Transactional 中指定 rollbackFor?

    作者 | Mint6 来源 | blog.csdn.net/Mint6/article/details/78363761 java阿里巴巴规范提示:方法[edit]需要在Transactional注解 ...

  7. Spring 事务之@Transactional

    在业务代码中,有如下两种情况,比如: throw new RuntimeException("xxxxxxxxxxxx"); 事务回滚 throw new Exception(&q ...

  8. Spring 事务管理@transactional 的实现原理和使用

    转载自:http://tech.lede.com/2017/02/06/rd/server/SpringTransactional/ 本文主要讨论Spring声明式事务中使用注解@Transactio ...

  9. Spring——事务注解@Transactional【建议收藏】

    在某些业务场景下,如果一个请求中,需要同时写入多张表的数据或者执行多条sql,为了保证操作的原子性(要么同时成功,要么同时失败),避免数据不一致的情况,我们一般都会用到事务:Spring框架下,我们经 ...

最新文章

  1. 记忆的天空:智能进化三部曲
  2. python类装饰器详解-Python装饰器基础概念与用法详解
  3. C语言经典例76-根据n的奇偶性累加
  4. fedora下安装pps
  5. js for foreach 快慢_js基本搜索算法实现与170万条数据下的性能测试
  6. for循环多次调用cuda kernel函数_CUDA程序设计入门(二)——核函数
  7. java js倒计时_Java实现倒计时的方法详解
  8. scala代码示例_Scala异常处理示例
  9. oreo授权系统V1.1开源版
  10. 弱网优化、网络抖动、网络延时,这些问题,怎么处理?
  11. python学习笔记(八)传递任意数量的实参
  12. 让游戏画面会说话,游戏音效制作有讲究
  13. 山东科技大学计算机学院奖学金,山东科技大学:一份特殊“奖学金”
  14. 企业想要制作电商类App软件
  15. html上下滑动视频代码,h5 实现视频手势上下屏滑动 (类似抖音)
  16. 零伽壹链改研究:供应链金融潜能爆发,解密背后的区块链技术应用!
  17. 优秀的项目跟踪管理软件有哪些?
  18. 3.2 写一个UR机器人运动学库
  19. [Demo]用简单的html,css做一个漂亮的网页!
  20. html标签可以嵌套吗,HTML标签的嵌套

热门文章

  1. IDEA中项目、模块和包的关系
  2. 大数据平台搭建,cdh选型配置
  3. java servlet php_servlet是什么
  4. MFC中使用Sqllite数据库
  5. Python Leetcode买卖股票
  6. 家用低功耗文件服务器,家用小型低功耗服务器配置
  7. linux下IM server搭建
  8. android登录插件设计,GitHub - yunpian/yunpian-onelogin-demo-android: 云片一键登录 Android Demo...
  9. 重庆春季高考计算机试题,卷01 2019年重庆市高等职业教育分类考试真题-冲刺2020年重庆市春季高考通用技术八套卷...
  10. 教你用Python写一个京东自动下单抢购脚本(Python实现京东自动抢购)