- 什么是事务?
事务就是以可控的方式对数据资源进行访问的一组操作,它有四个限定属性,原子性、一致性、隔离性、持久性,就是我们常称的ACID属性。 - 隔离性的四种隔离级别由弱到强分别是Read Uncommited、Read Commited、Repeatable Read、Serializable。
- Read Uncommited
最低的隔离级别,可以读取到其他事务未提交的数据,无法避免脏读,幻读,不可重复读等问题。- 脏读
读取到另一个事务未提交的数据,然后那个事务回滚了,那我们读到的数据就是脏数据。 - 不可重复读
在同一个事务中对同一笔数据进行多次读取,读取到的结果不完全相同。比如在Read Commited隔离级别,一个事务在另一个事务提交数据前读一次,提交后读一次,两次读取的结果不一致。 - 幻读
同一个事务中对多条记录(聚合操作也算)进行查询结果不完全相同的情况叫幻读,比如事务A查询表发现表为空,然后准备插入一个主键为1的数据,在事务A插入之前,事务B完成了插入主键为1数据的操作,在Repeatable Read级别,事务A对B事务的插入操作不可见(因为Repeatable Read能避免不可重复读),但当A事务插入数据时报错,发现表里已经有主键为1的数据了。
- 脏读
- Read Commited
隔离级别比Read Uncommited 高,通常是数据库默认的隔离级别,一个事务的更新操作只有在事务提交后才能被读取到。可以避免脏读,但无法避免幻读和不可重复读 - Repeatable Read
可重复读,它可以保证在整个事务过程中,对同一笔数据读取的结果是相同的,不管其他事务是否对该笔数据进行更新。可以避免脏读和不可重复读,但是不可避免幻读。 - Serializable
最为严格的隔离级别,所以操作必须按照顺序执行,可以避免所有的问题,但是效率最低
-
全局事务和局部事务
全局事务也叫分布式事务,通过两阶段提交协调多RM(Resource Manager一般是数据库)之间的事务处理,有个非常恰当的例子是婚礼上主持会分别问男女双方你愿意嫁给他吗?如果有任意一方拒绝,就各自回滚到单身状态。TP Monitor负责在分布式事务中协调多个RM的事务处理,TM是它的核心模块。
只有一个RM参与的就叫局部事务,它不必引进TP Monitor,应用程序可以直接和RM打交道,全局事务和局部事务的区别是涉及多少RM,如果系统中有多个RM,但是事务只涉及一个RM,同样是局部事务。
-
Spring事务
- TransactionDefinition
TransactionDefinition定义了事务的隔离级别,传播行为,事务的超时时间,是否为只读事务。
public interface TransactionDefinition {
/*传播行为*/
//如果当前存在一个事务,则加入当前事务,如果不存在,则新建一个事务,至少保证在一个事务中运行
int PROPAGATION_REQUIRED = 0;
//如果当前存在一个事务,则加入当前事务,如果不存在,则直接执行
int PROPAGATION_SUPPORTS = 1;
//强制要求当前存在一个事务,如果不存在则跑出异常
int PROPAGATION_MANDATORY = 2;
//不管当前是否存在事务,都会创建新的事务,如果当前存在事务会挂起当前事务
int PROPAGATION_REQUIRES_NEW = 3;
//不支持当前事务,在没有事务的情况下执行,如果当前存在事务,会挂起当前事务
int PROPAGATION_NOT_SUPPORTED = 4;
//永远不需要当前存在事务,如果存在则抛出异常
int PROPAGATION_NEVER = 5;
//如果存在当前事务,则在当前事务的一个嵌套事务中执行
int PROPAGATION_NESTED = 6;
/*隔离级别*/
//表示使用数据库默认的隔离级别
int ISOLATION_DEFAULT = -1;
//对应Read_Uncommitted隔离级别,无法避免脏读,不可重复读和幻读
int ISOLATION_READ_UNCOMMITTED = 1;
//对应Read Committed隔离级别,无法避免不可重复读和幻读
int ISOLATION_READ_COMMITTED = 2;
//对应Repeatable Read, 无法避免幻读
int ISOLATION_REPEATABLE_READ = 4;
//对应Serializable隔离级别,并发行最低,能避免所有问题
int ISOLATION_SERIALIZABLE = 8;
int TIMEOUT_DEFAULT = -1;
int getPropagationBehavior();
int getIsolationLevel();
int getTimeout();
boolean isReadOnly();
String getName();
}
-
PROPAGATION_SUPPORTS和PROPAGATION_NOT_SUPPORTS的区别
-
PROPAGATION_REQUIRES_NEW和PROPAGATION_NESTED的区别
- TransactionStatus
PlatfornTransactionManager的getTransaction会返回一个Transaction对象,可以通过它查询事务的状态
public interface TransactionStatus extends SavepointManager, Flushable {
boolean isNewTransaction();
boolean hasSavepoint();
//标记当前事务使其回滚
void setRollbackOnly();
boolean isRollbackOnly();
void flush();
boolean isCompleted();
}
- PlatformTransactionManager
public interface PlatformTransactionManager {
/*getTransaction会开启一个事务,但在此之前需要判断是否存在是否,
如果存在则根据传播行为决定是挂起事务或者抛出异常,
不存在事务,同样需要根据传播行为决定如何处理*/
TransactionStatus getTransaction(TransactionDefinition var1) throws TransactionException;
/*检测全局的rollBackOnly,如果被设置则执行回滚*/
void commit(TransactionStatus var1) throws TransactionException;
/*检测全局的rollBackOnly,如果没被设置则执行提交*/
void rollback(TransactionStatus var1) throws TransactionException;
}