掌柜大作战(17):Spring事务的原理,用自己的语言描述自己的理解

来源:互联网 发布:寻侠乐理突破数据 编辑:程序博客网 时间:2024/04/28 21:39
网上解读Spring事务原理的文章已经很多了,谈点自己的理解。
看别人的分析,很多时候有种“死记硬背”的感觉,看过了,然后又忘了。或者,不能很好地向别人表达自己的理解。
因此,自己写几句,梳理下思路。

一、Spring事务的基础:数据库事务
Spring事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring是无法提供事务功能的。对于纯JDBC操作数据库,想要用到事务,可以按照以下步骤进行:
1.获取连接 Connection con = DriverManager.getConnection()
2.开启事务con.setAutoCommit(true/false);
3.执行CRUD
4.提交事务/回滚事务 con.commit() / con.rollback();
5.关闭连接 conn.close();
无论Spring和Mybatis等框架怎么包装,底层数据库操作代码执行,还是上面的JDBC5步走。

二、使用AOP削减重复性代码
上面的1、2、4、5,明显是重复性代码。
经过Spring等框架的封装,我们写代码重点关注第3步,各种CRUD。
Spring是怎么减少开发者写重复性代码的?还是老一套,万能的AOP,AOP的基础是反射。
Spring中,可以使用注解定义事务,比如:
@Transactional
public void transferMoney(Integer userId,Integer money);

写一个AOP拦截相应的方法执行,如果目标类的方法A,包含了注解@Transactional,就执行before和after方法。
public void aop(ActionContext context){
//含有注解
before();
transferMoney();
after();
}
before方法:获得数据库连接,设置默认提交为false。
after方法:关闭数据库连接,提交commit或回滚rollback

三、Spring事务的传播属性
这是Spring的概念,不是数据库的概念。
注解@Transactional包含了propagation变量,定义了传播属性。
比如说,
PROPAGATION_REQUIRED支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择,也是 Spring 默认的事务的传播。

PROPAGATION_REQUIRES_NEW新建事务,如果当前存在事务,把当前事务挂起。新建的事务将和被挂起的事务没有任何关系,是两个独立的事务,外层事务失败回滚之后,不能回滚内层事务执行的结果,内层事务失败抛出异常,外层事务捕获,也可以不处理回滚操作。

如果事务管理器确定要创建新事务,那么将:

(Spring提出了一个事务管理器的概念)
1.创建一个新的entity manager
2.entity manager绑定到当前线程
3.从数据库连接池中获取连接
4.将连接绑定到当前线程
5.使用ThreadLocal变量将entity manager和数据库连接都绑定到当前线程。
事务运行时他们存储在线程中,当它们不再被使用时,事务管理器决定是否将他们清除。
程序的任何部分如果需要当前的entity manager和数据库连接都可以从线程中获取。

如果2个线程,2个业务方法,根据他们的上下文属性,获得了同一个collection,那就是“同一个事务”;如果是不同的collection,那就是“不同的事务”。

四、Spring事务和数据库事务的隔离级别
事务的隔离级别,是数据库底层控制的,Spring只是老实干活罢了。

隔离级别隔离级别的值导致的问题
Read-Uncommitted0导致脏读
Read-Committed1避免脏读,允许不可重复读和幻读
Repeatable-Read2避免脏读,不可重复读,允许幻读
Serializable3串行化读,事务只能一个一个执行,避免了脏读、不可重复读、幻读。执行效率慢,使用时慎重

脏读:一事务对数据进行了增删改,但未提交,另一事务可以读取到未提交的数据。如果第一个事务这时候回滚了,那么第二个事务就读到了脏数据。
不可重复读:一个事务中发生了两次读操作,第一次读操作和第二次操作之间,另外一个事务对数据进行了修改,这时候两次读取的数据是不一致的。
幻读:第一个事务对一定范围的数据进行批量修改,第二个事务在这个范围增加一条数据,这时候第一个事务就会丢失对新增数据的修改。

隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大。
大多数的数据库默认隔离级别为 Read Commited,比如 SqlServer、Oracle
少数数据库默认隔离级别为:Repeatable Read 比如: MySQL InnoDB

Spring的事务隔离级别
ISOLATION_DEFAULT这是个 PlatfromTransactionManager 默认的隔离级别
与JDBC的4个隔离级别相对应,看字符串名字就知道了。
ISOLATION_READ_UNCOMMITTED
ISOLATION_READ_COMMITTED
ISOLATION_REPEATABLE_READ
ISOLATION_SERIALIZABLE

五、参考文章
主要参考了以下4篇文章:
http://www.importnew.com/12300.html
http://www.cnblogs.com/duanxz/p/3750845.html
http://www.cnblogs.com/fjdingsd/p/5632949.html
http://www.cnblogs.com/superjt/p/4275293.html

总的来说,以上4篇文章已经对Spring事务的各方面实现做了完整的解读。
自己只是从新梳理了下思路,按照自己的理解。
毕竟,消化了才是自己的。
不然,过不了几天,又吐回去了。

哦耶~

小雷FansUnion-京东程序员一枚
2017年10月
北京-亦庄
阅读全文
0 0
原创粉丝点击