面试问题浓缩总结 面试问题浓缩总结
  • Go
  • Java
  • C/C++
  • JavaScript/HTML
  • MySQL
  • Redis
  • MongoDB
  • 操作系统
  • 计算机网络
  • spring全家桶
  • mybatis
  • 中间件
  • 软件相关
  • 系统相关
  • 算法
  • 数据结构
  • 设计模式
  • CMU硕士经典100题
  • 剑指offer
  • 重点手撕代码
  • 程序员面试金典
  • 3月
  • 4月
  • 智力题
  • 业务问题
  • 一些技术
  • 安全相关
APP下载 (opens new window)
GitHub (opens new window)
  • Go
  • Java
  • C/C++
  • JavaScript/HTML
  • MySQL
  • Redis
  • MongoDB
  • 操作系统
  • 计算机网络
  • spring全家桶
  • mybatis
  • 中间件
  • 软件相关
  • 系统相关
  • 算法
  • 数据结构
  • 设计模式
  • CMU硕士经典100题
  • 剑指offer
  • 重点手撕代码
  • 程序员面试金典
  • 3月
  • 4月
  • 智力题
  • 业务问题
  • 一些技术
  • 安全相关
APP下载 (opens new window)
GitHub (opens new window)
  • spring全家桶

    • IOC
    • AOP
    • spring MVC
    • springSecurity
    • 面试问题
    • 循环依赖
    • 事务
      • spring事务传播
        • PROPAGATION_REQUIRED (默认)
        • REQUIRES_NEW
        • NESTED
        • SUPPORTS
        • NOT_SUPPORTED
        • MANDATORY
        • NEVER
      • 事务隔离的五种级别
      • 事务失效的原因
    • 启动流程和配置
    • 注解相关
  • mybatis

  • 中间件

  • 框架
  • spring全家桶
小游
2021-03-26

事务

# spring事务传播

为什么要有事务传播呢?默认情况下,spring是使用aop来实现事务的,我们只需要在方法上面加上 @Transactional 注解就可以了,但是这个时候会有几个问题比如 serviceA 方法调用了 serviceB 方法,但两个方法都有事务,这个时候如果 serviceB 方法异常,是让 serviceB 方法提交,还是两个一起回滚?

这里我们就要用到事务传播了,spring提供了7中事务传播行为(使用@Transaction(Propagation=XXX)设置决定)

# PROPAGATION_REQUIRED (默认)

  • 支持当前事务,如果当前没有事务,则新建事务
  • 如果当前存在事务,则加入当前事务,合并成一个事务

# REQUIRES_NEW

  • 新建事务,如果当前存在事务,则把当前事务挂起
  • 这个方法会独立提交事务,不受调用者的事务影响,父级异常,它也是正常提交

# NESTED

  • 如果当前存在事务,它将会成为父级事务的一个子事务,方法结束后并没有提交,只有等父事务结束才提交
  • 如果当前没有事务,则新建事务
  • 如果它异常,父级可以捕获它的异常而不进行回滚,正常提交
  • 但如果父级异常,它必然回滚,这就是和 REQUIRES_NEW 的区别

# SUPPORTS

  • 如果当前存在事务,则加入事务
  • 如果当前不存在事务,则以非事务方式运行,这个和不写没区别

# NOT_SUPPORTED

  • 以非事务方式运行
  • 如果当前存在事务,则把当前事务挂起

# MANDATORY

  • 如果当前存在事务,则运行在当前事务中
  • 如果当前无事务,则抛出异常,也即父级方法必须有事务

# NEVER

  • 以非事务方式运行,如果当前存在事务,则抛出异常,即父级方法必须无事务

一般用得比较多的是 PROPAGATION_REQUIRED, REQUIRES_NEW;

REQUIRES_NEW 一般用在子方法需要单独事务

还有spring本身不提供事务功能,事务功能是数据库提供的

参考

  1. Spring事务传播行为详解 - SegmentFault 思否 (opens new window)
  2. spring 事务的传播机制看这篇就够了 - SegmentFault 思否 (opens new window)

# 事务隔离的五种级别

TransactionDefinition 接口中定义了五个表示隔离级别的常量:

  • TransactionDefinition.ISOLATION_DEFAULT: 使用后端数据库默认的隔离级别,Mysql 默认采用的 REPEATABLE_READ隔离级别 Oracle 默认采用的 READ_COMMITTED隔离级别.
  • TransactionDefinition.ISOLATION_READ_UNCOMMITTED: 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读
  • TransactionDefinition.ISOLATION_READ_COMMITTED: 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生
  • TransactionDefinition.ISOLATION_REPEATABLE_READ: 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。
  • TransactionDefinition.ISOLATION_SERIALIZABLE: 最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。

# 事务失效的原因

主要是这八点:

  1. 数据库引擎是否支持事务(比如MyISAM就不支持事务)
  2. 注解所在的类是否被加载成Bean
  3. 注解所在的方法是否为public所修饰
  4. 是否发生了自调用机制——同一个类之中的方法相互调用
  5. 所用的数据源是否加载了事务管理器
  6. @Transactional的扩展配置propagation是否正确(七种传播行为)
  7. 异常被吃掉了——自己try自己catch
  8. 异常抛出错误——抛的不是RuntimeException

image-20210409204919647

编辑 (opens new window)
上次更新: 2021/04/23, 21:43:16
循环依赖
启动流程和配置

← 循环依赖 启动流程和配置→

Theme by Vdoing | Copyright © 2021-2021 小游
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式