Spring:事务
摘要
本文摘抄了spring事务相关的一些理论,主要讲述事务的特性、事务的传播行为、事务的隔离规则。
关键词:事务特性,事务传播,事务隔离
一、什么是事务
事务是用来保证数据的完整性和一致性,正如金钱转账,金钱总数不会增加也不会减少。
数据库 事务管理有四个特性(acid):
特性 | 描述 |
---|---|
原子性(atomicity) | 事务作为一个整体被执行,要么全部被执行,要么都不执行。 |
一致性(consistency) | 事务应确保数据的状态从一个一致状态转变为另一个一致状态,数据不应该被破坏。 |
隔离性(isolation) | 多个事务并发执行时,一个事务的执行不应影响其他事务的执行。 |
持久性(durability) | 已被提交的事务对数据的修改应该永久性的。 |
二、spring事务管理器
1. 事务管理接口
spring中定义了事务管理的总接口platformtransactionmanager,该接口定义了以下几个接口来管理事务:
- gettransaction() - 获取事务状态(transactionstatus),该事务由(transactiondefinition定义)
- commit() - 提交事务
- rollback() - 回滚事务
spring不直接管理事务,而是提供一个事务管理接口,由其他平台(如jdbc、hibernate)自己实现事务管理。
几个具体的事务:
事务名称 | 管理器类 | 说明 |
---|---|---|
jdbc事务 | org.springframework.jdbc.datasource.datasourcetransactionmanager | 通过调用java.sql.connection来管理事务 |
hibernate | org.springframework.orm.hibernate3.hibernatetransactionmanager | 事务管理由org.hibernate.transaction对象负责 |
java持久化api事务(jpa) | org.springframework.orm.jpa.jpatransactionmanager | jpatransactionmanager与由工厂(javax.persistence.entitymanagerfactory)所产生的jpa entitymanager合作来构建事务 |
java原生api事务 | org.springframework.transaction.jta.jtatransactionmanager | jtatransactionmanager将事务管理的责任委托给javax.transaction.usertransaction和javax.transaction.transactionmanager对象(允许在多个数据库之间管理多个事务) |
关于jta,参考java中的事务——jdbc事务和jta事务
(spring事务管理器)
2. 事务管理与aop
spring通过aop拦截所有需要事务管理的业务处理方法。
三、spring事务属性
spring事务有几个属性,transactiondefinition接口可以体现出来:
public interface transactiondefinition { // 事务传播行为定义 int propagation_required = 0; int propagation_supports = 1; int propagation_mandatory = 2; int propagation_requires_new = 3; int propagation_not_supported = 4; int propagation_never = 5; int propagation_nested = 6; // 事务隔离级别定义 int isolation_default = -1; int isolation_read_uncommitted = connection.transaction_read_uncommitted; int isolation_read_committed = connection.transaction_read_committed; int isolation_repeatable_read = connection.transaction_repeatable_read; int isolation_serializable = connection.transaction_serializable; // 默认超时时间 int timeout_default = -1; // 获取事务传播行为 int getpropagationbehavior(); // 获取事务隔离级别 int getisolationlevel(); // 获取事务超时时间 int gettimeout(); // 获取事务是否只读 boolean isreadonly(); // 获取事务名字 string getname(); }
接口的定义加上回滚规则,事务可以有以下五个基本配置:事务传播行为、事务隔离级别、事务超时、事务只读、回滚规则
1. 传播行为
所谓传播行为(propagation behavior)指一个事务方法被另一个事务方法调用时,事务应该如何处理。被调用的方法可能在现有事务中运行,或者启动一个新的事务,在自己事务内运行。
传播行为 | 含义 | 解释 |
---|---|---|
propagation_required | 表示当前方法必须运行在事务中。如果当前事务存在,方法将会在该事务中运行。否则,会启动一个新的事务 | 有且只有一个事务 |
propagation_supports | 表示当前方法不需要事务上下文,但是如果存在当前事务的话,那么该方法会在这个事务中运行 | 如果方法单独调用则是非事务执行,如果方法被另一个有事务的方法调用,被调用方法则加入事务 |
propagation_mandatory | 表示该方法必须在事务中运行,如果当前事务不存在,则会抛出一个异常 | 如果单独非事务调用会抛异常,必须被其它事务方法调用,加入到事务中。 |
propagation_required_new | 表示当前方法必须运行在它自己的事务中。一个新的事务将被启动。如果存在当前事务,在该方法执行期间,当前事务会被挂起。如果使用jtatransactionmanager的话,则需要访问transactionmanager | 总是开启一个新的事务,原调用事务存在的话会被挂起,直至事务完成。 |
propagation_not_supported | 表示该方法不应该运行在事务中。如果存在当前事务,在该方法运行期间,当前事务将被挂起。如果使用jtatransactionmanager的话,则需要访问transactionmanager | 总是非事务地执行该方法,如果调用事务存在的话会被挂起,直至方法执行完成 |
propagation_never | 表示当前方法不应该运行在事务上下文中。如果当前正有一个事务在运行,则会抛出异常 | 总是非事务性执行方法,否则抛出异常 |
propagation_nested | 表示如果当前已经存在一个事务,那么该方法将会在嵌套事务中运行。嵌套的事务可以独立于当前事务进行单独地提交或回滚。如果当前事务不存在,那么其行为与propagation_required一样。注意各厂商对这种传播行为的支持是有所差异的。可以参考资源管理器的文档来确认它们是否支持嵌套事务 | 嵌套事务一个非常重要的概念就是内层事务依赖于外层事务。外层事务失败时,会回滚内层事务所做的动作。而内层事务操作失败并不会引起外层事务的回滚。 |
2. 隔离规则
事务的执行会存在并发的,隔离级别定义了一个事务受其它并发事务影响的程度。
有两个表格:
并发事务引起的问题
问题 | 定义 | 出现原因 |
---|---|---|
脏读 | 读到无效的数据 | 当一个事务读取了另一个事务修改但未提交的数据,如果修改回滚,则事务读取了无效的数据。 |
不可重复读 | 同一个事务中两次相同查询中,读取到不同的数据 | 一个事务两次查询期间,另一个并发事务对数据进行了更新。 |
幻读 | 同一个事务在两次相同的查询中,读取到不同记录数的数据 | 一个事务两次查询期间,另一个并发事务进行了数据新增或删除。 |
隔离级别
隔离级别 | 说明 | 并发事务可能引起的问题 |
---|---|---|
isolation_default | 使用后端数据库默认的隔离级别 | 具体情况具体分析 |
isolation_read_uncommitted | 最低的隔离级别,允许读取尚未提交的数据变更 | 脏读、不可重复读、幻读 |
isolation_read_committed | 允许读取并发事务已经提交的数据 | 不可重复读、幻读 |
isolation_repeatable_read | 对同一字段的多次读取结果一致,除非字段被本事务修改 | 幻读 |
isolation_serializable | 最高的隔离级别,完全服从acid原则,通常通过锁表实现(最慢) | 无 |
3. 事务超时
给定事务一个超时时间,如果特定时间事务没有执行完毕,事务会自动回滚。
4. 是否只读?
设置了只读事务,那么在此事务执行过程中,其它事务对数据库的修改对于该事务来说是透明的,即看不到其它事务修改后的数据。这通常用于执行多次查询来统计信息时,能够保证数据的整体一致性。
5. 回滚规则
回滚规则定义了哪些异常,事务会进行回滚。默认情况下,事务只有遇到运行时异常才会回滚,而在遇到检查型异常时不会回滚。
四、spring事务管理形式
1. 编程式事务
使用transactiontemplate或platformtransactionmanager
transactiontemplate tt = new transactiontemplate(); tt.execute(status -> { // 执行操作 dosth(); // 返回操作结果 return obj; });
2. 声明式事务
六、总结
- spring定义了事务管理器的接口,具体实现由特定平台来实现;
- spring事务有五个属性:事务传播行为、事务隔离级别、事务超时、事务只读、回滚规则;
- 传播行为:required、supports、mandatory、required_new、not_support、never、nested;
- 隔离级别:default、read_uncommited、read_committed、repeatable_read、serializable;
参考资料
推荐阅读
-
spring boot踩坑记
-
spring boot从redis取缓存发生java.lang.ClassCastException异常
-
spring-boot-2.0.3不一样系列之源码篇 - run方法(三)之createApplicationContext,绝对有值得你看的地方
-
简单了解Spring Web相关模块运行原理
-
Spring Boot @Scheduled定时任务代码实例解析
-
基于Nacos实现Spring Cloud Gateway实现动态路由的方法
-
Spring 事务隔离与事务传播的详解与对比
-
详解Spring Controller autowired Request变量
-
JSP 获取Spring 注入对象示例
-
Spring AOP中使用args表达式的方法示例