文章目录
一、基本概念
一组业务操作
二、四个特性(ACID)
2.1 原子性
事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生
2.2 一致性
事务前后数据的完整性必须保持一致
2.3 隔离性
事务的隔离性是指多个用户并发访问数据库时,一个用户的事务不能被其它用户的事务所干扰,多个并发事务之间数据要相互隔离
2.4 持久性
持久性是指一个事务一旦提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响
极端情况(系统服务崩溃或重启):
1.事务的执行过程中(未提交):事务所有的操作就会被回滚,即回到事务操作之前的状态
2.事务的执行过程中(已提交): 数据为事务操作执行后的状态
三、事务管理的三大接口
3.1 PlatformTransactionManager 平台事务管理器
public interface PlatformTransactionManager {
// 获取事务状态(根据事务详情获取事务状态,从而管理事务)
TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
// 根据状态提交
void commit(TransactionStatus status) throws TransactionException;
// 根据状态回滚
void rollback(TransactionStatus status) throws TransactionException;
}
常见事务管理器:
- DataSourceTransactionManager :JDBC单数据库事务管理器
- HibernateTransactionManager :Hibernate事务管理器
- JpaTransactionManager:分布式事务管理器
3.2 TransactionDefinition 事务详情(事务属性)
事务五边形:
3.2.1 七大传播行为
传播行为:在两个业务之间如何共享事务
传播行为 | 含义 | 描述 | 支持事务 | 创建新事务 | 回滚规则 |
---|---|---|---|---|---|
REQUIRED | 必须 (默认值) | A有事务B加入;A没有事务B创建 | 是 | 不一定 | 存在一个事务:1.外部有事务加入,异常回滚;2.外部没事务创建新事务:异常回滚 |
SUPPORTS | 支持 | A有事务B加入;A没有事务B非事务 | 是 | 否 | 最多只存在一个事务:1.外部有事务加入,异常回滚;2.外部没事务,内部非事务,异常不回滚 |
MANDATORY | 强制 | A有事务B加入;A没有事务B抛异常 | 是 | 否 | 最多只存在一个事务:1.外部有事务加入,异常回滚;2.外部不存在事务,异常无法回滚 |
REQUIRES_NEW | 必须新 | A有事务A挂起B创建,A没有事务B创建 | 是 | 是 | 可能存在1-2个事务:1.外部存在事务挂起,创建新事务,异常回滚自己的事务;2.外部不存在事务,创建新事务,异常只回滚新事务 |
NOT_SUPPORTED | 不支持 | A有事务A挂起B非事务,A没有事务B非事务 | 否 | 否 | 最多只存在一个事务:1.外部有事务挂起,外部异常回滚;内部非事务,异常不回滚;2.外部无事务,内部非事务,异常不回滚 |
NEVER | 从不 | A有事务B抛异常,A没有事务B非事务 | 否 | 否 | 最多只存在一个事务:1.外部有事务挂起,外部异常回滚;内部非事务不回滚;2.外部非事务,内部非事务,异常不回滚 |
NESTED | 嵌套 | AB采用保存点机制,嵌套事务 | 是 | 否 | 存在一个事务:1.外部有事务,嵌套事务创建保存点,外部异常回滚全部事务;内部嵌套事务异常回滚到保存点;2.外部不存在事务,内部创建新事务,内部异常回滚 |
掌握:REQUIRED、REQUIRES_NEW、NESTED
3.2.2 四大隔离级别
1、隔离问题:
多个线程开启各自事务操作数据库中的数据时,数据库系统要负责隔离操作,以保证各个线程在获取数据时的准确性。如果不考虑隔离,可能会引发如下问题
- 脏读:一个事务读到另一个事务没有提交的数据; 脏读被认为是数据库中的最重要问题,是不被任何数据库所允许的
- 不可重复读:一个事务读到另一个事务已提交的数据(update); 不可重复读在有些数据库被认为是没有问题的,所以它在某些数据库中允许出现
- 虚读(幻读):一个事务读到另一个事务已提交的数据(insert); 同样,虚读在有些数据库也被认为不是问题,允许该现象出现
危害级别由高到低:脏读>不可重复读>虚读
2、隔离级别:定义了一个事务可能受其他并发事务影响的程度
隔离级别 | 含义 | 脏读 | 不可重复读 | 虚读 |
---|---|---|---|---|
Read uncommitted | 读未提交 | 未解决 | 未解决 | 未解决 |
Read committed | 读已提交 | 解决 | 未解决 | 未解决 |
Repeatable read | 可重复读 | 解决 | 解决 | 未解决 |
Serializable | 串行化 | 解决 | 解决 | 解决 |
隔离级别由高到低:Serializable>Repeatable read>Read committed>Read uncommitted;
安全级别高,是以降低性能和并发性为代价的;
3、数据库隔离级别的查询及修改
mysql8.0:
查询:
select @@global.transaction_isolation; //全局事务
select @@transaction_isolation; //当前会话事务
修改:
set global transaction isolation level read committed; //全局事务
set session transaction isolation level repeatable read; //当前会话事务
默认Repeatable read
3.2.3 只读
这是事务的第三个特性,是否为只读事务。如果事务只对后端的数据库进行该操作,数据库可以利用事务的只读特性来进行一些特定的优化。通过将事务设置为只读,你就可以给数据库一个机会,让它应用它认为合适的优化措施。
3.2.4 事务超时
为了使应用程序很好地运行,事务不能运行太长的时间。因为事务可能涉及对后端数据库的锁定,所以长时间的事务会不必要的占用数据库资源。事务超时就是事务的一个定时器,在特定时间内事务如果没有执行完毕,那么就会自动回滚,而不是一直等待其结束
3.3 TransactionStatus 事务状态
四、Spring两种实现方式
- 编程式事务管理
编程式事务管理使用底层源码可实现更细粒度的事务控制。spring推荐使用TransactionTemplate,典型的模板模式 - 声明式事务管理
添加@Transactional注解,并定义传播机制+回滚策略。基于Spring AOP实现,本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务