Talking about Spring Transaction Isolation Level

1. Propagation (propagation properties of transactions)

Propagation : The key property determines which method the proxy should add transactional behavior to. The most important part of such a property is the propagation behavior. The following options are available: PROPAGATION_REQUIRED--support the current transaction, if there is no current transaction, create a new transaction. This is the most common choice.
PROPAGATION_SUPPORTS--Support the current transaction, if there is no current transaction, it will be executed in a non-transactional manner.
PROPAGATION_MANDATORY--Supports the current transaction, if there is no current transaction, an exception is thrown.
PROPAGATION_REQUIRES_NEW--Create a new transaction, if there is a current transaction, suspend the current transaction.
PROPAGATION_NOT_SUPPORTED--Perform the operation in a non-transactional manner, suspending the current transaction if there is a current transaction.
PROPAGATION_NEVER--Execute in a non-transactional manner, throwing an exception if there is currently a transaction.

1: PROPAGATION_REQUIRED
is added to the transaction currently being executed is not in another transaction, then a new transaction is started.
For example, the transaction level of ServiceB.methodB is defined as PROPAGATION_REQUIRED, then when ServiceA.methodA is executed,
ServiceA.methodA has already started After the transaction is completed, ServiceB.methodB is called at this time. ServiceB.methodB sees that it is already running inside
the transaction of ServiceA.methodA, so it will not start a new transaction. And if ServiceA.methodA runs and finds that he is not in a transaction, he will assign himself a transaction.
This way, if an exception occurs in ServiceA.methodA or anywhere within ServiceB.methodB, the transaction will be rolled back. Even if the transaction of ServiceB.methodB has been
committed, but ServiceA.methodA will be rolled back in the next fail, ServiceB.methodB will also be rolled back

2: PROPAGATION_SUPPORTS
If it is currently in a transaction, that is, it runs in the form of a transaction. If it is no longer in a transaction, it runs in a non-transactional form.


3: PROPAGATION_MANDATORY
must be run in a transaction. That is, he can only be called by a parent transaction. Otherwise, he will throw an exception

4: PROPAGATION_REQUIRES_NEW
This is a bit of a twist. For example, we design the transaction level of ServiceA.methodA to be PROPAGATION_REQUIRED, and the transaction level of ServiceB.methodB to be PROPAGATION_REQUIRES_NEW,
then when ServiceB.methodB is executed, the transaction where ServiceA.methodA is located will hang, and ServiceB.methodB will start a new one Transaction, waits for ServiceB.methodB's transaction to complete before
he continues to execute. The difference between him and the PROPAGATION_REQUIRED transaction is the degree of rollback of the transaction. Because ServiceB.methodB is a new transaction, then there are
two different transactions. If ServiceB.methodB has been submitted, then ServiceA.methodA fails and rolls back, but ServiceB.methodB will not roll back. If ServiceB.methodB fails and rolls back,
if the exception he throws is caught by ServiceA.methodA, the ServiceA.methodA transaction may still commit.

5: PROPAGATION_NOT_SUPPORTED
Transactions are not currently supported. For example, the transaction level of ServiceA.methodA is PROPAGATION_REQUIRED, and the transaction level of ServiceB.methodB is PROPAGATION_NOT_SUPPORTED,
then when ServiceB.methodB is executed, the transaction of ServiceA.methodA is suspended, and he finishes running in a non-transactional state, and then continues ServiceA .methodA's transaction.

6: PROPAGATION_NEVER
不能在事务中运行。假设ServiceA.methodA的事务级别是PROPAGATION_REQUIRED, 而ServiceB.methodB的事务级别是PROPAGATION_NEVER ,
那么ServiceB.methodB就要抛出异常了。

7: PROPAGATION_NESTED
理解Nested的关键是savepoint。他与PROPAGATION_REQUIRES_NEW的区别是,PROPAGATION_REQUIRES_NEW另起一个事务,将会与他的父事务相互独立,
而Nested的事务和他的父事务是相依的,他的提交是要等和他的父事务一块提交的。也就是说,如果父事务最后回滚,他也要回滚的。
而Nested事务的好处是他有一个savepoint。
*****************************************
ServiceA {

/**
* 事务属性配置为 PROPAGATION_REQUIRED
*/
void methodA() {
try {
//savepoint
ServiceB.methodB(); //PROPAGATION_NESTED 级别
} catch (SomeException) {
// 执行其他业务, 如 ServiceC.methodC();
}
}

}
********************************************
也就是说ServiceB.methodB失败回滚,那么ServiceA.methodA也会回滚到savepoint点上,ServiceA.methodA可以选择另外一个分支,比如
ServiceC.methodC,继续执行,来尝试完成自己的事务。

那么什么是嵌套事务呢?很多人都不理解,我看过一些博客,都是有些理解偏差。

嵌套是子事务套在父事务中执行,子事务是父事务的一部分,在进入子事务之前,父事务建立一个回滚点,叫save point,然后执行子事务,这个子事务的执行也算是父事务的一部分,然后子事务执行结束,父事务继续执行。重点就在于那个save point。看几个问题就明了了:

如果子事务回滚,会发生什么? 

父事务会回滚到进入子事务前建立的save point,然后尝试其他的事务或者其他的业务逻辑,父事务之前的操作不会受到影响,更不会自动回滚。


如果父事务回滚,会发生什么? 

父事务回滚,子事务也会跟着回滚!为什么呢,因为父事务结束之前,子事务是不会提交的,我们说子事务是父事务的一部分,正是这个道理。那么:


事务的提交,是什么情况? 

是父事务先提交,然后子事务提交,还是子事务先提交,父事务再提交?答案是第二种情况,还是那句话,子事务是父事务的一部分,由父事务统一提交。


但是这个事务并没有在EJB标准中定义。

Spring事务的隔离级别
 1. ISOLATION_DEFAULT: 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别.
      另外四个与JDBC的隔离级别相对应
 2. ISOLATION_READ_UNCOMMITTED: 这是事务最低的隔离级别,它充许令外一个事务可以看到这个事务未提交的数据。
      这种隔离级别会产生脏读,不可重复读和幻像读。
 3. ISOLATION_READ_COMMITTED: 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据
 4. ISOLATION_REPEATABLE_READ: 这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。
      它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)。
 5. ISOLATION_SERIALIZABLE 这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。
      除了防止脏读,不可重复读外,还避免了幻像读。

什么是脏数据,脏读,不可重复读,幻觉读?
 脏读: 指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,
     另外一个事务也访问这个数据,然后使用了这个数据。因为这个数据是还没有提交的数据, 那么另外一
     个事务读到的这个数据是脏数据,依据脏数据所做的操作可能是不正确的。
    
 不可重复读: 指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。
             那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的数据
             可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。
            
 幻觉读: 指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及
         到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,
         以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325578298&siteId=291194637