一、事务特性(ACID)
原子性:事务内所有的更改操作(先关联的所有数据操作),作为一个单元进行提交或者回滚。
一致性:事务保证数据库从一个一致状态变到另一个一致状态。(要么所有操作成功,要么所有操作回滚)
隔离性:与事务隔离性和隔离级别有关。
持久性:数据更改永久性。
二、事务操作
JDBC 事务、JTA事务、容器事务。
JDBC事务只能操作同一数据库,不可分布式。
JDBC 默认自动提交,可通过 Connection 的 setAutoCommit(false) 方法开启。
setAutoCommit(false); // 取消自动提交
commit(); // 提交事务
rollback(); // 事务回滚
JTA事务,JAVA Transaction API。可进行分布式数据库操作。
JTA 分为两部分,
Transaction Manager(事务管理器,提供给开发者使用)
Resource Manager(支持XA协议的资源管理器,提供给数据服务商使用)
JTA 通过 begin() 方法开启一个事务
begin(); // 开启事务
commit(); // 提交事务
rollback(); // 事务回滚
。。。
容器事务
三、隔离级别
不同的隔离级别可能发生事务并发问题:
脏读:一个事物读取了另一个事务未提交(commit)的数据。
不可重复读:一个事物在另一个事务修改数据前后分别读取,读取的数据不一致;与脏读区别:脏读读取了未提交的数据。
幻读:事物 T1 修改了表中字段值,比如flag=2,然后事务 T2 添加新的数据,数据的flag=1,此时修改字段的事务会出现幻读。
MySQL 提供的四种隔离级别:默认 Read committed
Serializable:串行化;不存在脏读、不可重复读、幻读
Repeatable Read:可重复读;不会出现幻读;读的是快照结果,所以其他事务修改数据后,不影响该事务
Read committed:读已提交;可避免脏读
Read uncommitted:读未提交;最低级的,所有情况都可能发生
JDBC 设置隔离级别:
在 setAutoCommit(false) 之前,调用 Connection 的
setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE)
只对当前 connection 有效
四、Spring 事务传播特性
spring 七中传播特性
1、PROPAGATION_REQUIRED:如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的设置。
2、PROPAGATION_SUPPORTS:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行。‘
3、PROPAGATION_MANDATORY:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常。
4、PROPAGATION_REQUIRES_NEW:创建新事务,无论当前存不存在事务,都创建新事务。
5、PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
6、PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
7、PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。
一般的基于 spring 的开发,如果 service 层中使用注解开启事务的话:
public void methodA() {
methodB();
}
@Transactional
public void methodB() {
}
当 controller 层调用 methodA() 时,不会开启事务,因为是 同类方法 调用的 methodB,不会进行AOP(@Transactional)切面