参考:
MySQL的四种事务隔离级别
透彻的掌握 Spring 中@transactional 的使用事务逻辑上的一组操作,组成这组操作的各个逻辑单元,要么一起成功,要么一起失败.
小结:不可重复读的和幻读很容易混淆,不可重复读侧重于 修改 ,幻读侧重于 新增或删除 。解决不可重复读的问题只需 锁住满足条件的行 ,解决幻读需要 锁表
Mysql 默认:可重复读 select @@tx_isolation
Oracle 默认:已提交读
是最低的事务隔离级别,它允许另外一个事务可以看到这个事务未提交的数据。
保证一个事物提交后才能被另外一个事务读取。另外一个事务不能读取该事物未提交的数据。
这种事务隔离级别可以防止脏读,不可重复读。但是可能会出现幻象读。它除了保证一个事务不能被另外一个事务读取未提交的数据之外还避免了以下情况产生(不可重复读)。
这是花费最高代价但最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读之外,还避免了幻象读(避免三种)。
隔离级别 | 脏读 | 不可重复读 | 虚读(幻读) |
---|---|---|---|
未提交读 | 可能 | 可能 | 可能 |
已提交读 | 不可能 | 可能 | 可能 |
可重复读 | 不可能 | 不可能 | 可能 |
串行化 | 不可能 | 不可能 | 不可能 |
propagation :事务的传播行为
项 | 行为 |
---|---|
PROPAGATION_REQUIRED | 支持当前事务,如果不存在 就新建一个(默认) |
PROPAGATION_SUPPORTS | 支持当前事务,如果不存在,就不使用事务 |
PROPAGATION_MANDATORY | 支持当前事务,如果不存在,抛出异常 |
项 | 行为 |
---|---|
PROPAGATION_REQUIRES_NEW | 如果有事务存在,挂起当前事务,创建一个新的事务 |
PROPAGATION_NOT_SUPPORTED | 以非事务方式运行,如果有事务存在,挂起当前事务 |
PROPAGATION_NEVER | 以非事务方式运行,如果有事务存在,抛出异常 |
PROPAGATION_NESTED | 如果当前事务存在,则嵌套事务执行 |
默认情况下,如果在事务中抛出了unchecked异常(继承自 RuntimeException 的异常)或者 Error,则 Spring 将回滚事务;除此之外,Spring 不会回滚事务。
如果在事务中抛出其他类型的异常,并期望 Spring 能够回滚事务,可以指定
rollbackFor = {XException.class, YException.class}
只有@Transactional 注解应用到 public 方法,才能进行事务管理。这是因为在使用 Spring AOP 代理时,Spring 在调用在图 1 中的 TransactionInterceptor
在目标方法执行前后进行拦截之前, DynamicAdvisedInterceptor
(CglibAopProxy 的内部类)的 intercept 方法或 JdkDynamicAopProxy
的 invoke 方法会间接调用 AbstractFallbackTransactionAttributeSource
(Spring 通过这个类获取 @Transactional 注解的事务属性配置属性信息)的 computeTransactionAttribute 方法。
这个方法会检查目标方法的修饰符是不是 public,若不是 public,就不会获取 @Transactional 的属性配置信息,最终会造成不会用 TransactionInterceptor 来拦截该目标方法进行事务管理
在 Spring 的 AOP 代理下,只有目标方法由外部调用,目标方法才由 Spring 生成的代理对象来管理,这会造成自调用问题。若同一类中的其他没有@Transactional 注解的方法内部调用有@Transactional 注解的方法,有@Transactional 注解的方法的事务被忽略,不会发生回滚