ACID特性
原子性(Atomicity)事务必须是一个不可分割的整体,就像我们在化学课里学到的原子,原子是构成物质的最小单位。
一致性(Consistency)执行完数据库操作后,数据不会被破坏。打个比方,如果从 A 账户转账到 B 账户,不可能因为 A 账户扣了钱,而 B 账户没有加钱吧。
隔离性(Isolation)保证数据库操作之间是“隔离”的(线程之间有时也要做到隔离),彼此之间没有任何干扰。
持久性(Durability)数据库必须要保证有一条数据永久地存放在磁盘
这 4 条特性,是事务管理的基石,原子性是基础,隔离性是手段,持久性是目的,最重要的就是一致性。
事务并发引发的问题
Dirty Read(脏读)事务 A 读取了事务 B 未提交的数据,并在这个基础上又做了其他操作。
Unrepeatable Read(不可重复读)事务 A 读取了事务 B 已提交的更改数据。
Phantom Read(幻读)事务 A 读取了事务 B 已提交的新增数据。
JDBC的解决方案
获取默认隔离级别
DatabaseMetaData meta = DBUtil.getDataSource().getConnection().getMetaData();
int defaultIsolation = meta.getDefaultTransactionIsolation();
spring的解决方案
事务传播行为(Transaction Propagation Behavior)Spring 解决的只是方法之间的事务传播
假设事务从方法 A 传播到方法 B,面对方法 B,问自己一个问题,方法 A 有事务吗?
PROPAGATION_REQUIRED 如果没有,就新建一个事务;如果有,就加入当前事务。Spring 提供的默认事务传播行为,适合绝大多数情况。
RROPAGATION_REQUIRES_NEW 如果没有,就新建一个事务;如果有,就将当前事务挂起。意思就是创建了一个新事务,它和原来的事务没有任何关系了。
PROPAGATION_NESTED 如果没有,就新建一个事务;如果有,就在当前事务中嵌套其他事务。当主事务提交或回滚,子事务也会提交或回滚。
PROPAGATION_SUPPORTS 如果没有,就以非事务方式执行;如果有,就使用当前事务。
PROPAGATION_NOT_SUPPORTED 如果没有,就以非事务方式执行;如果有,就将当前事务挂起。
PROPAGATION_NEVER 如果没有,就以非事务方式执行;如果有,就抛出异常。
PROPAGATION_MANDATORY 如果没有,就抛出异常;如果有,就使用当前事务。
事务超时(Transaction Timeout)
为了解决事务时间太长,消耗太多的资源,所以给事务设置一个最大时长,如果超过了,就回滚事务。
只读事务(Readonly Transaction)
为了忽略那些不需要事务的方法,比如读取数据,这样可以有效地提高一些性能。
ps:
可在 @Transactional 注解中设置:事务隔离级别、事务传播行为、事务超时时间、是否只读事务。