1、事务 ACID 特性:
(1)原子性(Atomicity):必须是一个不可分割的整体,要么做完,要么就不做;
(2)一致性(Consistency):不可能因为 A 账户扣了钱,而 B 账户没有加钱;
(3)隔离性(Isolation):数据库操作之间是“隔离”(线程之间也要做到隔离);
事务隔离级别(Transaction Isolation Level):
- READ_UNCOMMITTED
- READ_COMMITTED
- REPEATABLE_READ
- SERIALIZABLE
》》》从上往下,级别越高,并发性越差,安全性越高,反之则反;
(4)持久性(Durability):数据库插入数据,永久地存放在磁盘;
2、原子性是基础,隔离性是手段,持久性是目的,真正的老大就是一致性;
- Dirty Read(脏读):事务 A 读取了事务 B 未提交的数据,并在这个基础上又做了其他操作;
- Unrepeatable Read(不可重复读):事务 A 读取了事务 B 已提交的更改数据;
- Phantom Read(幻读):事务 A 读取了事务 B 已提交的新增数据;
- 第一条是坚决抵制的,后两条在大多数情况下可不作考虑;
3、Spring事务传播行为(Transaction Propagation Behavior),对 JDBC 的一个补充或扩展;
- PROPAGATION_REQUIRED
- RROPAGATION_REQUIRES_NEW
- PROPAGATION_NESTED
- PROPAGATION_SUPPORTS
- PROPAGATION_NOT_SUPPORTED
- PROPAGATION_NEVER
- PROPAGATION_MANDATORY
- 如果没有,就新建一个事务;如果有,就加入当前事务。这就是 PROPAGATION_REQUIRED,它也是 Spring 提供的默认事务传播行为,适合绝大多数情况。
- 如果没有,就新建一个事务;如果有,就将当前事务挂起。这就是 RROPAGATION_REQUIRES_NEW,意思就是创建了一个新事务,它和原来的事务没有任何关系了。
- 如果没有,就新建一个事务;如果有,就在当前事务中嵌套其他事务。这就是 PROPAGATION_NESTED,也就是传说中的“嵌套事务”了,所嵌套的子事务与主事务之间是有关联的(当主事务提交或回滚,子事务也会提交或回滚)。
- 如果没有,就以非事务方式执行;如果有,就使用当前事务。这就是 PROPAGATION_SUPPORTS,这种方式非常随意,没有就没有,有就有,有点无所谓的态度,反正我是支持你的。
- 如果没有,就以非事务方式执行;如果有,就将当前事务挂起。这就是 PROPAGATION_NOT_SUPPORTED,这种方式非常强硬,没有就没有,有我也不支持你,把你挂起来,不鸟你。
- 如果没有,就以非事务方式执行;如果有,就抛出异常。这就是 PROPAGATION_NEVER,这种方式更猛,没有就没有,有了反而报错,确实够牛的,它说:我从不支持事务!
- 如果没有,就抛出异常;如果有,就使用当前事务。这就是 PROPAGATION_MANDATORY,这种方式可以说是牛逼中的牛逼了,没有事务直接就报错,确实够狠的,它说:我必须要有事务!
- 事务超时(Transaction Timeout):为了解决事务时间太长,消耗太多的资源,所以故意给事务设置一个最大时常,如果超过了,就回滚事务。
- 只读事务(Readonly Transaction):为了忽略那些不需要事务的方法,比如读取数据,这样可以有效地提高一些性能。
4、Spring 的注解式事务配置(优雅):《《《《《《《《《《《《《《《《《《《《《《《《《《
<tx:annotation-driven /> //在 Spring 配置文件中使用
@Transactional
public void xxx() {//在需要事务的方法上使用
...
}
5、思维导图