Spring transaction propagation properties and isolation levels

1 Propagation of transactions 

1) REQUIRED, this is the default property 
Support a current transaction, create a new one if none exists. 
If there is a transaction, the current transaction is supported. If there is no transaction, start a new transaction. 
When set to this level, a logical transaction domain is created for each method called. If the previous method has already created a transaction, the latter method supports the current transaction and re-establishes the transaction if there is no current transaction. 
As shown in the figure: 

2) MANDATORY 
Support a current transaction, throw an exception if none exists. Support the current transaction, if there is no current transaction, throw an exception. 

3) NEVER 
Execute non-transactionally, throw an exception if a transaction exists 


4) NOT_SUPPORTED 
Execute non-transactionally, suspend the current transaction if one exists. 
Execute the operation in a non-transactional manner. If a transaction currently exists, suspend the current transaction. 

5) REQUIRES_NEW 
Create a new transaction, suspend the current transaction if one exists 

As shown in the figure: 

6) SUPPORTS 
Support a current transaction, execute non-transactionally if none exists 


7) NESTED 
Execute within a nested transaction if a current transaction exists, behave like PROPAGATION_REQUIRED else. 
Support current transaction, add Savepoint, commit or rollback synchronously with current transaction. 
A very important concept of nested transactions is that the inner transaction depends on the outer transaction. When the outer transaction fails, the actions done by the inner transaction are rolled back. The failure of the inner transaction operation will not cause the rollback of the outer transaction. 

8) The difference between PROPAGATION_NESTED and PROPAGATION_REQUIRES_NEW 
They are very similar, they are like a nested transaction, if there is no active transaction, a new transaction will be opened. When using PROPAGATION_REQUIRES_NEW, the inner transaction and the outer transaction are like two independent transactions. Once the inner transaction is committed, the outer transaction cannot be rolled back. The two transactions do not affect each other. Two transactions are not a true nested transaction. At the same time it requires the support of the JTA transaction manager. 
When PROPAGATION_NESTED is used, the rollback of the outer transaction can cause the rollback of the inner transaction. The exception of the inner transaction will not cause the rollback of the outer transaction, it is a real nested transaction. 

2 Isolation Level of 

Transactions 1) First, explain the three situations caused by transaction concurrency 

i. Dirty Reads 
A transaction is updating data, but the update has not yet been committed, and another transaction is also operating at this time. This group of data is read, and the data that has not been committed by the previous transaction is read, and the previous transaction is rolled back if the operation fails, and the latter transaction reads the wrong data, which results in dirty reads.

ii. Non-Repeatable Reads Non-Repeatable Reads 
A transaction reads the same data multiple times. Before the transaction ends, another transaction also operates on the data, and between the two reads of the first transaction , the second transaction updates the data, then the data read before and after the first transaction is different, which results in non-repeatable reads.

iii. Phantom Reads phantom reads 
the first data and is querying data that meets a certain condition. At this time, another transaction inserts another piece of data that meets the condition. When the first transaction queries the data that meets the same condition for the second time, It is found that there is an extra piece of data that was not available in the previous query, as if it were an illusion. This is phantom read.

iv. The difference between distinct degree and phantom read Distinct 
read means that the same query is performed multiple times in the same transaction, and different result sets are returned each time due to modifications or deletions made by other committing transactions, and a distinct read occurs at this time. . (A transaction rereads data it has previously read and finds that another committed transaction has modified or deleted the data. )

幻像读是指同一查询在同一事务中多次进行,由于其他提交事务所做的插入操作,每次返回不同的结果集,此时发生幻像读。(A transaction reexecutes a query returning a set of rows that satisfies a search condition and finds that another committed transaction has inserted additional rows that satisfy the condition. )

表面上看,区别就在于非重复读能看见其他事务提交的修改和删除,而幻像能看见其他事务提交的插入。 

2) DEFAULT (默认) 
这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别.另外四个与JDBC的隔离级别相对应 

3) READ_UNCOMMITTED (读未提交) 
这是事务最低的隔离级别,它允许另外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读。 

4) READ_COMMITTED (读已提交) 
保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。这种事务隔离级别可以避免脏读出现,但是可能会出现不可重复读和幻像读。 

5) REPEATABLE_READ (可重复读) 
这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了不可重复读 

6) SERIALIZABLE(串行化) 
这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读外,还避免了幻像读。 

7) 隔离级别解决事务并行引起的问题 
Dirty reads non-repeatable reads phantom reads 
Serializable 不会 不会 不会 
REPEATABLE READ 不会 不会 会 
READ COMMITTED 不会 会 会 
Read Uncommitted 会 会 会


事物传播行为介绍: 
@Transactional(propagation=Propagation.REQUIRED) 
如果有事务, 那么加入事务, 没有的话新建一个(默认情况下)
@Transactional(propagation=Propagation.NOT_SUPPORTED) 
容器不为这个方法开启事务
@Transactional(propagation=Propagation.REQUIRES_NEW) 
不管是否存在事务,都创建一个新的事务,原来的挂起,新的执行完毕,继续执行老的事务
@Transactional(propagation=Propagation.MANDATORY) 
必须在一个已有的事务中执行,否则抛出异常
@Transactional(propagation=Propagation.NEVER) 
必须在一个没有的事务中执行,否则抛出异常(与Propagation.MANDATORY相反)
@Transactional(propagation=Propagation.SUPPORTS) 
如果其他bean调用这个方法,在其他bean中声明事务,那就用事务.如果其他bean没有声明事务,那就不用事务.

事物超时设置:
@Transactional(timeout=30) //默认是30秒

事务隔离级别:
@Transactional(isolation = Isolation.READ_UNCOMMITTED)
读取未提交数据(会出现脏读, 不可重复读) 基本不使用
@Transactional(isolation = Isolation.READ_COMMITTED)
读取已提交数据(会出现不可重复读和幻读)
@Transactional(isolation = Isolation.REPEATABLE_READ)
可重复读(会出现幻读)
@Transactional(isolation = Isolation.SERIALIZABLE)
串行化

MYSQL: 默认为REPEATABLE_READ级别
SQLSERVER: 默认为READ_COMMITTED

脏读 : 一个事务读取到另一事务未提交的更新数据
不可重复读 : 在同一事务中, 多次读取同一数据返回的结果有所不同, 换句话说, 
后续读取可以读到另一事务已提交的更新数据. 相反, "可重复读"在同一事务中多次
读取数据时, 能够保证所读数据一样, 也就是后续读取不能读到另一事务已提交的更新数据
幻读 : 一个事务读到另一个事务已提交的insert数据



 关于嵌套事物

  可能大家对PROPAGATION_NESTED还不怎么了解,觉得有必要再补充一下^_^!
PROPAGATION_NESTED: 嵌套事务类型,是相对上面提到的六种情况(上面的六种应该称为平面事务类型),打个比方我现在有一个事务主要有一下几部分:
      1,从A用户帐户里面减去100元钱
      2,往B用户帐户里面添加100元钱
       这样看和以前不同的事务可能没有什么区别,那我现在有点特殊的要求就是,A用户有3个帐户,B用户有2个帐户,现在我的要求就是只要再A用户的3个帐户里面任意一个减去100元,往B用户的两个帐户中任意一个里面增加100元就可以了!
       一旦你有这样的要求那嵌套事务类型就非常适合你!我们可以这样理解,
       一:将“从A用户帐户里面减去100元钱” 和 “往B用户帐户里面增加100元钱”我们暂时认为是一级事务操作
       二:将从A用户的3个帐户的任意一个帐户里面减钱看做是“从A用户帐户里面减去100元钱”这个一级事务的子事务(二级事务),同样把后面存钱的看成是另一个的二级事务。
      问题一:当二级事务被rollback一级事务会不会被rollback?
      答案是不会的,二级事务的rollback只针对自己。
      问题二:什么时候这个一级事务会commit,什么时候会被rollback呢?
      我们主要看二级里面出现的情况,当所有的二级事务被commit了并且一级事务没有失败的操作,那整个事务就算是一个成功的事务,这种情况整个事务会被commit。
当任意一个二级事务没有被commit那整个事务就是失败的,整个事务会被roolback。
还是拿上面的例子来说明吧!如果我在a的三个帐户里面减钱的操作都被二级事务给rollback了,也就是3个帐户里面都没有减钱成功,整个事务就失败了就会被rollback。如果A用户帐户三个帐户里面有一个可以扣钱而且B用户的两个帐户里面也有一个帐户可以增加钱,那整个事务就算成功的,会被 commit。
看了一下觉得上面的例子好像不是很深刻,看这个情况(A用户的3个帐户都是有信用额度的,也就是说可以超支,但是超支有金额限制)。不过原理是一样的,简单点也好说明一点,祝你好运!^_^ 

Guess you like

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