Transaction propagation behavior and isolation levels

Dirty read: A transaction is accessing data, and modifications have been made to the data, but it has not been committed to the database. At this time, another transaction reads this part of the uncommitted data

 

Non-repeatable read: refers to reading the same data multiple times within a transaction. Before this transaction has ended, another transaction has modified the data. Then, between two reads of data in the first transaction, due to the modification of the second transaction, the data read twice by the first transaction may be different. In this way, the data read twice in a transaction is different, so it is called non-repeatable read.

The point of non-repeatable read is to modify: 

Under the same conditions, the data you have read, read it again and find that the value is different.

 

Phantom read: A phenomenon that occurs when transactions are not executed independently. For example, the first transaction modifies the data in a table, such as this modification involves "all data rows" in the table. At the same time, the second transaction also modifies the data in this table by inserting "a new row of data" into the table. Then, it will happen later that the user who operates the first transaction finds that there are no modified data rows in the table, as if a hallucination occurred.

The point of phantom reading is to add or delete 

Under the same conditions, the number of records read out the first time and the second time are different.

 

In order to solve the above three problems, the following isolation levels have emerged:

ISOLATION_READ_UNCOMMITTED

This is the lowest isolation level for a transaction, which allows another transaction to see the uncommitted data of this transaction. This isolation level produces dirty reads, non-repeatable reads and phantom reads

 

ISOLATION_READ_COMMITTED 

It is guaranteed that the data modified by one transaction can only be read by another transaction after it is committed. Another transaction cannot read the transaction's uncommitted data. This transaction isolation level can avoid dirty reads, but non-repeatable reads and phantom reads may occur. (locks the row being read)

 

ISOLATION_REPEATABLE_READ 

This transaction isolation level prevents dirty reads and non-repeatable reads. However, phantom reads may occur. In addition to ensuring that a transaction cannot read uncommitted data of another transaction, it also ensures that the following situation (non-repeatable read) is avoided. (locks all rows read)

 

ISOLATION_SERIALIZABLE

This is the most expensive but most reliable transaction isolation level. Transactions are processed for sequential execution. In addition to preventing dirty reads, non-repeatable reads, it also avoids phantom reads. (lock table)

 

spread behavior

REQUIRED——Support the current transaction, if there is no current transaction, create a new transaction. This is the most common choice.

 

SUPPORTS——Support the current transaction, if there is no current transaction, it will run in a non-transactional mode.

 

MANDETORY——Support the current transaction, if there is no current transaction, an exception is thrown.

 

REQUIRES_NEW————Always create a new transaction. If there is currently a transaction, suspend the current transaction.

 

NOT_SUPPORTED——Run under non-transaction, if there is a current transaction, suspend the current transaction.

 

NEVER——Runs under non-transaction, throws an exception if there is currently a transaction.

 

NESTED——If an active transaction exists, run in a nested transaction, if there is no active transaction, execute according to the REQUIRED attribute.

 

The following example analyzes these 6 propagation behaviors:

ServiceA {   

    

     /**  

      * The transaction property is configured as PROPAGATION_REQUIRED  

      */  

     void methodA() {   

         ServiceB.methodB();   

     }   

  

}   

  

ServiceB {   

       

     /**  

      * The transaction property is configured as PROPAGATION_REQUIRED  

      */    

     void methodB() {   

     }   

       

}      ************************************************* 

1:PROPAGATION_REQUIRED 

Assuming that the transaction currently being executed is not in another transaction, a new transaction is started.

For example, the transaction level of ServiceB.methodB is defined as PROPAGATION_REQUIRED, then since ServiceA.methodA has already started a transaction when ServiceA.methodA is executed, ServiceB.methodB is called at this time, and ServiceB.methodB sees that it is already running in ServiceA.methodA Inside the transaction, no new transaction is started. 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, it runs in the form of a transaction, and if it is not currently in a transaction, it runs in a non-transactional form. This is only a little different from the normal non-transactional code that is usually used. Ignore this because I don't see any difference either.

 

3:PROPAGATION_MANDATORY 

Must run within 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 rather convoluted. 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 

Cannot run in a transaction. Assuming that the transaction level of ServiceA.methodA is PROPAGATION_REQUIRED, and the transaction level of ServiceB.methodB is PROPAGATION_NEVER, then ServiceB.methodB will throw an exception.

 

7:PROPAGATION_NESTED 

The key to understanding Nested is the savepoint. The difference between him and PROPAGATION_REQUIRES_NEW is that PROPAGATION_REQUIRES_NEW starts another transaction, which will be independent of his parent transaction, while Nested's transaction is dependent on his parent transaction, and his submission is to be submitted together with his parent transaction. . That is, if the parent transaction rolls back last, he will also roll back. And the nice thing about Nested affairs is that he has a savepoint. 

***************************************** 

ServiceA {   

       

     /**  

      * The transaction property is configured as PROPAGATION_REQUIRED  

      */  

     void methodA() {   

         try { 

      //savepoint   

             ServiceB.methodB();    //PROPAGATION_NESTED 级别 

         } catch (SomeException) {   

             // Execute other business, such as ServiceC.methodC();   

         }   

     }   

  

}   

******************************************** 

That is to say, if ServiceB.methodB fails to roll back, then ServiceA.methodA will also roll back to the savepoint point. ServiceA.methodA can choose another branch, such as 

ServiceC.methodC, continue to execute, to try to complete its own transaction. 

 

important point:

Two conditions must be met to createSavepoint: 

1. java.sql.Savepoint must exist, that is, the jdk version must be 1.4+ 

2. Connection.getMetaData().supportsSavepoints() must be true, that is, jdbc drive must support JDBC 3.0 

After making sure the above conditions are met, you can try to use PROPAGATION_NESTED.

 

Reference blog: http://dapeng.iteye.com/blog/155178

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326942049&siteId=291194637