一、概念
由单个用户或者应用程序执行的,完成读取或者更新数据库内容的一个或者多个操作。
也就是包含多条DML的操作。
二、事务特性
- 原子性:事务不可分割,要么全部执行,要么都不执行。
- 一致性:事务将数据库从一种一致性状态转换到另一种一致性状态。数据库
只保证数据符合约束,而数据的逻辑正确性应该由应用程序来保证。 - 隔离性:事务的执行相互独立,没有完成的事务的中间结果对其他事物不可见。
- 持久性:成功提交的事务被永久记录到数据库文件中。
三、并发控制
- 丢失更新问题:一个事务A进行更新操作,事务B的更新覆盖了事务A的更新。解决办法:禁止事务A读取数据,直到B更新完毕。
- 未提交依赖问题(污读问题):一个事务A看到另一个未提交的事务B的中间结果,事务B回滚。解决办法:不允许事务读取未提交的事务的中间结果。
- 不一致分析问题(2种):
- 一个事务A从数据库中读多个值,另一个事务B在读取过程中
修改了某些数据的值。解决办法:在完成更新操作前,禁止A事务的读取。
- 一个事务A从数据库中读多个值,另一个事务B在读取过程中
- 当T再次从数据库读取已经读取过的数据,两次读操作之间有其他事务修改数据,T得到两个不同的值。(不可重复读)
- 当T执行某一查询,另一个事务执行了插入,之后T再执行这个查询,发现查询结果包含了其他的元组。(幻读)
四、Mysql隔离级别
- 读未提交
- A可以读B未提交的数据(脏读)
- 读提交
- A提交后B才能读取到
- 可以避免脏读,无法避免不可重复读。、
- 可重复读(Mysql默认级别)
- A提交后的数据,B读取不到
- 避免脏读、不可重复读、无法避免幻读
- 串行化
- A操作数据库时,B只能排队等待
- 解决幻读
五、Spring事务
Spring事务简化了传统的数据库事务流程
- 分类
- 编程式事务:通过API,在代码中调用beginTransaction,commit,rollback函数进行事务管理。
- 声明式事务:通过AOP实现的,本质是对方法前后进行拦截,在方法开始之前创建/加入一个事务,执行完方法后根据情况提交/回滚
- 编程式事务
- 根据PlatformTransactionManager,TransactionDefinition,
TransactionStatus几个接口编程实现。 - TransactionDefination定义隔离级别、传播行为
- TransactionStatus=txManager.getTransaction(); 开启事务
- txManager.commit() 提交事务 rollback()回滚事务
- 声明式事务
- XML方式
- Tx:advice配置事务相关的通知
- Tx:attributes
- Tx:method
- Tx:attributes
- Aop:config配置AOP
- Aop:pointcut定义切入点
- Aop:advisor 定义切面,关联切入点与通知
- Tx:advice配置事务相关的通知
- 注解方式@Transactional
- 使用范围:通常类或者类的方法上进行注解,类上的注解应用到所有的public方法上。少数在接口和接口的方法上。
- Spring事务对数据库的处理:Mysql默认开启事务自动提交(此时不能够在代码中主动的commit),spring先关闭数据库的自动提交,然后执行方法,执行完毕后开启自动提交。
- 使用方法:@Transactional(propagation=传播行为,isolation=隔离级别)
- 开启事务注解驱动 tx:annotation-driven
- isolation参数指定隔离级别
- propagation指定传播行为
- rollbackFor指定需要让事务回滚的checked异常
- norollbackFor指定不让回滚的unchecked异常
- XML方式
六、Spring事务传播
事务传播:一个事务方法A被另一个事务方法B调用,A应该如何处理?事务A应该运行在B中还是新建一个事务?
TransactionDefination定义的传播行为:
int PROPAGATION_REQUIRED = 0; //如果存在一个事务,支持当前事务,如果当前没有事务,则新建一个。默认。
int PROPAGATION_SUPPORTS = 1;//如果存在一个事务,则支持当前事务。如果没有事务,则以非事务的方式执行。
int PROPAGATION_MANDATORY = 2;//如果已经存在一个事务,支持当前事务。如果当前没有事务,抛出IllegalTransactionStateException异常。
int PROPAGATION_REQUIRES_NEW = 3;//新建事务,如果当前存在一个事务,挂起当前事务。事务A与事务B是独立的。外层事务(调用另一个事务的调用者)回滚,不会影响内层事务的提交。使用JtaTransactionManager作为事务管理器。
int PROPAGATION_NOT_SUPPORTED = 4;//总是以非事务方式运行。如果当前存在事务,则挂起当前事务
int PROPAGATION_NEVER = 5;//以非事务方式运行。如果当前存在事务,抛出异常
int PROPAGATION_NESTED = 6;//如果有一个活动的事务,运行在嵌套的事务中,如果当前没有活动的事务,按照REQUIRED执行。外层事务失败,会回滚内层事务所做的动作。使用DataSourceTransactionManager
七、事务回滚规则
首先引入Java异常处理体系和分类
spring只会回滚unchecked异常,checked异常不会回滚,如果需要指定回滚checked异常,使用rollbackFor参数,如果不想回滚unchecked异常,指定norollbackFor参数
参考文献
【1】Java EE框架整合开发入门到实战:Spring+Spring MVC+MyBatis(微课版)
【2】数据库系统 设计 实现与管理 基础篇_第六版
【3】Spring AOP https://www.cnblogs.com/joy99/p/10941543.html
【4】Spring事务和Mysql事务https://blog.csdn.net/weixin_48272905/article/details/108525283
【5】Transactional详解https://blog.csdn.net/jiangyu1013/article/details/84397366