(Transfer) Transaction Propagation Behavior (Better Speaking)

Original text: http://blog.sina.com.cn/s/blog_4b5bc0110100z7jr.html
 
 
Article one:

We all know the concept of transactions, so what are the propagation characteristics of transactions? (The concept of propagation features is emphasized here, and the related configuration of propagation features is not introduced. You can check the official documents of spring.) 
When we develop projects with SSH, we generally set transactions in the Service layer, so when we use SSH to develop projects When calling a method of the Service layer, it can ensure that all the update operations to the database performed in this method are kept in a transaction, and these methods called in the transaction layer either all succeed or all fail. Then the propagation characteristics of transactions also start from here. 
If in this method of your Service layer, in addition to calling the Dao layer method, you also call other Service methods of this class, then when calling other Service methods, how is this transaction specified? , I must ensure that the method I use in my method is in the same transaction as my own method, otherwise if the consistency of things is guaranteed. The propagation feature of transactions solves this problem. "Transactions are propagated." In Spring, there are multiple configurations for propagation features. In most cases, we only use one of them: PROPGATION_REQUIRED: This configuration item means that when When I call the method of the service layer, I start a transaction (the method of which layer is called to start the transaction depends on the configuration of your aop), then when calling other methods in the service layer, if the current method generates If the transaction is completed, the transaction generated by the current method is used, otherwise a new transaction is created. This work is done by Spring to help us. 
In the past, when there was no Spring to help us complete the transaction, we had to manually control the transaction. For example, when we only used hibernate in our project and did not integrate into spring, we called other business logic methods in a service layer to ensure things. You must also pass the current hibernate session to the next method, or use the ThreadLocal method to pass the session to the next method, which is actually a purpose. Now that this work is done by spring to help us, we can focus more on our business logic. Don't worry about business issues. 

By default, when a RuntimeException occurs, the transaction will be rolled back, so pay attention if you have your own exception handling mechanism to define your own Exception in the event of a program error, you must inherit from the RuntimeException class so that the transaction will be roll back!

 

Article two:
 

transaction behavior and isolation level

Definition of transactions in Spring:
1. Propagation:
  The key attribute 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. 

Many people don't know much about the propagation behavior properties of transactions. When I watched j2ee without ejb last night, I didn't understand it here. I even re-read the textbook of the database system, but I didn't find any analysis on this. . Searched today and found an excellent analysis article, although this article focuses on the analysis of PROPAGATION_REQUIRED and
PROPAGATION_REQUIRED_NESTED spring nested transactions
********TransactionDefinition interface definition********************


     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;   

**************************************************** ************************
In this article, he uses two nested examples to assist the analysis, which I quote directly here.
********************sample***********************
ServiceA {   void methodA() {   ServiceB.methodB();   }   }   ServiceB {   void methodB() {   }   
       
       
     
         
     
  

  

       
         
     
     
       
}      
*************************************************
我们这里一个个分析吧
1: PROPAGATION_REQUIRED 
加入当前正要执行的事务不在另外一个事务里,那么就起一个新的事务
比如说,ServiceB.methodB的事务级别定义为PROPAGATION_REQUIRED, 那么由于执行ServiceA.methodA的时候,
          ServiceA.methodA已经起了事务,这时调用ServiceB.methodB,ServiceB.methodB看到自己已经运行在ServiceA.methodA
的事务内部,就不再起新的事务。而假如ServiceA.methodA运行的时候发现自己没有在事务中,他就会为自己分配一个事务。
这样,在ServiceA.methodA或者在ServiceB.methodB内的任何地方出现异常,事务都会被回滚。即使ServiceB.methodB的事务已经被
提交,但是ServiceA.methodA在接下来fail要回滚,ServiceB.methodB也要回滚
2:    PROPAGATION_SUPPORTS
如果当前在事务中,即以事务的形式运行,如果当前不再一个事务中,那么就以非事务的形式运行
这就跟平常用的普通非事务的代码只有一点点区别了。不理这个,因为我也没有觉得有什么区别
3:    PROPAGATION_MANDATORY
必须在一个事务中运行。也就是说,他只能被一个父事务调用。否则,他就要抛出异常。
4:    PROPAGATION_REQUIRES_NEW
这个就比较绕口了。 比如我们设计ServiceA.methodA的事务级别为PROPAGATION_REQUIRED,ServiceB.methodB的事务级别为PROPAGATION_REQUIRES_NEW,
那么当执行到ServiceB.methodB的时候,ServiceA.methodA所在的事务就会挂起,ServiceB.methodB会起一个新的事务,等待ServiceB.methodB的事务完成以后,
他才继续执行。他与PROPAGATION_REQUIRED 的事务区别在于事务的回滚程度了。因为ServiceB.methodB是新起一个事务,那么就是存在
两个不同的事务。如果ServiceB.methodB已经提交,那么ServiceA.methodA失败回滚,ServiceB.methodB是不会回滚的。如果ServiceB.methodB失败回滚,
如果他抛出的异常被ServiceA.methodA捕获,ServiceA.methodA事务仍然可能提交。
5:    PROPAGATION_NOT_SUPPORTED 
当前不支持事务。比如ServiceA.methodA的事务级别是PROPAGATION_REQUIRED ,而ServiceB.methodB的事务级别是PROPAGATION_NOT_SUPPORTED ,
那么当执行到ServiceB.methodB时,ServiceA.methodA的事务挂起,而他以非事务的状态运行完,再继续ServiceA.methodA的事务。
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 {   
       
        
      void methodA() {   
          try {
       //savepoint   
              ServiceB.methodB();     //PROPAGATION_NESTED 级别
          } catch (SomeException) {   
              // 执行其他业务, 如 ServiceC.methodC();   
          }   
      }   
  
}   
********************************************
也就是说ServiceB.methodB失败回滚,那么ServiceA.methodA也会回滚到savepoint点上,ServiceA.methodA可以选择另外一个分支,比如
ServiceC.methodC,继续执行,来尝试完成自己的事务。
但是这个事务并没有在EJB标准中定义。

二、Isolation Level(事务隔离等级):
1、Serializable:最严格的级别,事务串行执行,资源消耗最大;

2、REPEATABLE READ:保证了一个事务不会修改已经由另一个事务读取但未提交(回滚)的数据。避免了“脏读取”和“不可重复读取”的情况,但是带来了更多的性能损失。

3、READ COMMITTED:大多数主流数据库的默认事务等级,保证了一个事务不会读到另一个并行事务已修改但未提交的数据,避免了“脏读取”。该级别适用于大多数系统。

4、Read Uncommitted:保证了读取过程中不会读取到非法数据。
隔离级别在于处理多事务的并发问题。
我们知道并行可以提高数据库的吞吐量和效率,但是并不是所有的并发事务都可以并发运行,这需要查看数据库教材的可串行化条件判断了。
这里就不阐述。
我们首先说并发中可能发生的3中不讨人喜欢的事情
1:    Dirty reads--读脏数据。也就是说,比如事务A的未提交(还依然缓存)的数据被事务B读走,如果事务A失败回滚,会导致事务B所读取的的数据是错误的。

2:    non-repeatable reads--数据不可重复读。比如事务A中两处读取数据-total-的值。在第一读的时候,total是100,然后事务B就把total的数据改成200,事务A再读一次,结果就发现,total竟然就变成200了,造成事务A数据混乱。

3:    phantom reads--幻象读数据,这个和non-repeatable reads相似,也是同一个事务中多次读不一致的问题。但是non-repeatable reads的不一致是因为他所要取的数据集被改变了(比如total的数据),但是phantom reads所要读的数据的不一致却不是他所要读的数据集改变,而是他的条件数据集改变。比如Select account.id where account.name="ppgogo*",第一次读去了6个符合条件的id,第二次读取的时候,由于事务b把一个帐号的名字由"dd"改成"ppgogo1",结果取出来了7个数据。
                           Dirty reads           non-repeatable reads             phantom reads
Serializable                      不会                    不会                            不会
REPEATABLE READ            不会                    不会                             
READ COMMITTED             不会                     会                              
Read Uncommitted             会                      会                              

三、readOnly
事务属性中的readOnly标志表示对应的事务应该被最优化为只读事务。这是一个最优化提示。在一些情况下,一些事务策略能够起到显著的最优化效果,例如在使用Object/Relational映射工具(如:Hibernate或TopLink)时避免dirty checking(试图“刷新”)。
四、Timeout
        在事务属性中还有定义“timeout”值的选项,指定事务超时为几秒。在JTA中,这将被简单地传递到J2EE服务器的事务协调程序,并据此得到相应的解释。 事务的传播行为(讲得比较好)

Guess you like

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