数据库事务的四大特性(ACID)
- 原子性(Atomicity)事务是一个原子操作,由一系列动作组成。事务的原子性确保动作要么全部完成,要么完全不起作用。
- 一致性(Consistency)事务在完成时,必须是所有的数据都保持一致状态。
- 隔离性(Isolation)并发事务执行之间无影响,在一个事务内部的操作对其他事务是不产生影响,这需要事务隔离级别来指定隔离性。
- 持久性(Durability)一旦事务完成,数据库的改变必须是持久化的。
并发访问数据库导致的问题
在企业级应用中,多用户访问数据库是常见的场景,这就是所谓的事务的并发。事务并发所可能存在的问题:
- 脏读:一个事务读到另一个事务未提交的更新数据。
- 不可重复读:一个事务两次读同一行数据,可是这两次读到的数据不一样。
- 幻读:一个事务执行两次查询,但第二次查询比第一次查询多出了一些数据行。
- 丢失更新:撤消一个事务时,把其它事务已提交的更新的数据覆盖了。
应对并发访问导致问题的举措
上述四种并发访问数据库导致的问题是并发情况下难免会发生的,但是又是不得不解决的问题。在JDBC中,数据库事务有四大隔离级别:
- SERIALIZABLE(串行化)
- 不会出现任何并发问题,因为它是对同一数据的访问是串行的,非并发访问的;
- 性能最差;
- REPEATABLE READ (可重复读)(MySQL)
- 防止脏读和不可重复读,不能处理幻读问题;
- 性能比SERIALIZABLE好
- READ COMMITTED (读已提交数据)(Oracle)
- 防止脏读,没有处理不可重复读,也没有处理幻读;
- 性能比REPEATABLE READ好
- READ UNCOMMITTED (读未提交数据)
- 可能出现任何事务并发问题
- 性能最好
理解:例如当数据库事务的隔离级别是读已提交,那么当前事务对数据进行了更改,只要是该事务还没有提交,那么其他事务对数据的更改是看不见的.
Spring中对事务的处理
Spring事务管理高层抽象主要包括3个接口:
PlatformTransactionManager 事务管理器
我们常常使用的DataSourceTransactionManager就是它的一个间接子类
TransactionDefinition 事务定义信息(隔离、传播、超时、只读)
主要定义了它自己的传播行为和隔离级别
TransactionStatus 事务具体运行状态
主要方法:
1
2
3
4
5
6void flush(); //如果适用的话,这个方法用于刷新底层会话中的修改到数据库,例如,所有受影响的Hibernate/JPA会话。
boolean hasSavepoint(); // 是否有恢复点
boolean isCompleted(); // 是否已完成
boolean isNewTransaction(); // 是否是新的事务
boolean isRollbackOnly(); // 是否为只回滚
void setRollbackOnly(); // 设置为只回滚
声明式事务管理
声明式事务管理是非侵入式的
xml方式配置
1 | </beans> |
基于注解的配置方式
基于注解的方式简单好理解,是常用的方式
在xml配置文件中:
1 | <beans> |
然后在业务层中开启事务
1 | public class UserServiceImpl2 implements UserService { |
@Transactional可以标记在方法上,当标记在方法上的时候,代表此方法作为一个事务的原子操作,该方法中的内容是事务中事务体.
@Transactional也可以标记在类上,当标记在类上面的时候,代表此类中的所有方法都开启了事务.
编程式事务管理
编程式事务管理是侵入性的,用的不多
请参考 Spring事务管理详解