spring 事务——一篇文章搞定谜团

本文整理自:腾讯教育-图灵学院昭君老师视频

事务特性(4种): 

原子性 (atomicity):强调事务的不可分割. 

一致性 (consistency):事务的执行的前后数据的完整性保持一致. 

隔离性 (isolation):一个事务执行的过程中,不应该受到其他事务的干扰 

持久性(durability) :事务一旦结束,数据就持久到数据库

涉及的3个接口:


spring 事务——一篇文章搞定谜团

spring 事务——一篇文章搞定谜团

spring 事务——一篇文章搞定谜团

因数据库隔离级别不同出现的安全性问题:

1.脏读 :一个事务读到了另一个事务的未提交的数据 
2.不可重复读 :一个事务读到了另一个事务已经提交的 update 的数据导致多次查询结果不一致. 
3.虚幻读 :一个事务读到了另一个事务已经提交的 insert 的数据导致多次查询结果不一致.

为了解决这三种安全性问题引入了几种事务隔离级别:

解决读问题: 设置事务隔离级别(5种) 
DEFAULT 这是一个PlatfromTransactionManager默认的隔离级别,
使用数据库默认的事务隔离级别. 
未提交读(read uncommited) :脏读,不可重复读,虚读都有可能发生 
已提交读 (read commited):避免脏读。但是不可重复读和虚读有可能发生 
可重复读 (repeatable read) :避免脏读和不可重复读.但是虚读有可能发生. 
串行化的 (serializable) :避免以上所有读问题. 

Mysql 默认:可重复读 repeatable read
Oracle 默认:读已提交read commited

spring 事务——一篇文章搞定谜团

如果出现事务嵌套,那么久设计事务的传播行为:

第一组:

PROPAGATION_REQUIRED 支持当前事务,如果不存在 就新建一个(默认) 
PROPAGATION_SUPPORTS 支持当前事务,如果不存在,就不使用事务 
PROPAGATION_MANDATORY 支持当前事务,如果不存在,抛出异常 

第二组:

PROPAGATION_REQUIRES_NEW 如果有事务存在,挂起当前事务,创建一个新的事务 

第三组:

PROPAGATION_NOT_SUPPORTED 以非事务方式运行,如果有事务存在,挂起当前事务 
PROPAGATION_NEVER 以非事务方式运行,如果有事务存在,抛出异常 
PROPAGATION_NESTED 如果当前事务存在,则嵌套事务执行
 

实践

测试事务:
 

案例1:A 有事务、B也有事务,然后A 事务中调用B 方法,都使用默认的传播行为,不去手动设置

首先要明白一个问题:

spring事务的 默认传播行为是PROPAGATION_REQUIRED 支持当前事务,如果不存在 就新建一个(默认) 

spring 事务——一篇文章搞定谜团

spring 事务——一篇文章搞定谜团

spring 事务——一篇文章搞定谜团

结论:使用spring 默认的事务传播行为 A 中 调用 B 方法,B中的事务会加入当前事务,只产生一个事务

案例2:将案例1 中的 B方法的事务改为PROPAGATION_REQUIRES_NEW

spring 事务——一篇文章搞定谜团

spring 事务——一篇文章搞定谜团

结论:根据日志显示 出现挂起,新建的现象也就是2个事务。

源码:

spring 事务——一篇文章搞定谜团

 

针对下面4种情况分别讨论:

spring 事务——一篇文章搞定谜团

第一种 不做处理

案例3:B方法中 仍然使用新建,但是在方法最后抛出一个未处理的异常


spring 事务——一篇文章搞定谜团

spring 事务——一篇文章搞定谜团

结论:A、B 都进行了回滚

原因分析: 

spring 事务——一篇文章搞定谜团

第二种:B抛出异常由A内部处理

spring 事务——一篇文章搞定谜团

spring 事务——一篇文章搞定谜团

 

spring 事务——一篇文章搞定谜团

结论:B回滚、A继续提交

第三种:如果将第二种的 B 方法的 事务行为改成PROPAGATION_REQUIRES 会怎么样

spring 事务——一篇文章搞定谜团

spring 事务——一篇文章搞定谜团

第4种情况: 

 spring 事务——一篇文章搞定谜团

结果:A、B都提交,不回滚

第五种 情况:

spring 事务——一篇文章搞定谜团

spring 事务——一篇文章搞定谜团

结论:B 回滚、A提交

 

第六种:如果异常是发生A方法中 回事怎么样呢???

spring 事务——一篇文章搞定谜团

开始验证:

spring 事务——一篇文章搞定谜团

spring 事务——一篇文章搞定谜团

spring 事务——一篇文章搞定谜团

结论:都回滚

第七种:

如果B事务改成PROPAGATION_REQUIRES_NEW,B运行无异常,但是A出现异常会是什么情况??

spring 事务——一篇文章搞定谜团

 

spring 事务——一篇文章搞定谜团

结论:A新建事务, 挂起当前、B创建一个新事务提交、此时A 方法异常 A回滚、但B不回滚