Spring @Transactional - 隔离,传播

本文翻译自:Spring @Transactional - isolation, propagation

Can someone explain what isolation & propagation parameters are for in the @Transactional annotation via real-world example? 有人可以通过真实世界的例子解释@Transactional注释中的隔离传播参数吗?

Basically when and why I should choose to change their default values. 基本上何时以及为什么我应该选择更改其默认值。


#1楼

参考:https://stackoom.com/question/ZcrE/Spring-Transactional-隔离-传播


#2楼

PROPAGATION_REQUIRED = 0 ; PROPAGATION_REQUIRED = 0 ; If DataSourceTransactionObject T1 is already started for Method M1.If for another Method M2 Transaction object is required ,no new Transaction object is created .Same object T1 is used for M2 如果已经为方法M1启动了DataSourceTransactionObject T1。如果需要另一个方法M2事务对象,则不会创建新的Transaction对象.Same对象T1用于M2

PROPAGATION_MANDATORY = 2 ; PROPAGATION_MANDATORY = 2 ; method must run within a transaction. 方法必须在事务中运行。 If no existing transaction is in progress, an exception will be thrown 如果没有正在进行的事务,则会抛出异常

PROPAGATION_REQUIRES_NEW = 3 ; PROPAGATION_REQUIRES_NEW = 3 ; If DataSourceTransactionObject T1 is already started for Method M1 and it is in progress(executing method M1) .If another method M2 start executing then T1 is suspended for the duration of method M2 with new DataSourceTransactionObject T2 for M2.M2 run within its own transaction context 如果已经为方法M1启动了DataSourceTransactionObject T1并且它正在进行中(执行方法M1)。如果另一个方法M2开始执行,则T1在方法M2的持续时间内被暂停,其中新的DataSourceTransactionObject T2用于M2.M2在其自己的事务上下文中运行

PROPAGATION_NOT_SUPPORTED = 4 ; PROPAGATION_NOT_SUPPORTED = 4 ; If DataSourceTransactionObject T1 is already started for Method M1.If another method M2 is run concurrently .Then M2 should not run within transaction context. 如果已经为方法M1启动了DataSourceTransactionObject T1。如果另一个方法M2同时运行。那么M2不应该在事务上下文中运行。 T1 is suspended till M2 is finished. T1暂停直到M2完成。

PROPAGATION_NEVER = 5 ; PROPAGATION_NEVER = 5 ; None of the methods run in transaction context. 这些方法都不在事务上下文中运行。

An isolation level: It is about how much a transaction may be impacted by the activities of other concurrent transactions.It a supports consistency leaving the data across many tables in a consistent state. 隔离级别:它是关于事务可能受其他并发事务的活动影响的程度。它支持一致性,使数据保持在一致状态的多个表中。 It involves locking rows and/or tables in a database. 它涉及锁定数据库中的行和/或表。

The problem with multiple transaction 多个交易的问题

Scenario 1 .If T1 transaction reads data from table A1 that was written by another concurrent transaction T2.If on the way T2 is rollback,the data obtained by T1 is invalid one.Eg a=2 is original data .If T1 read a=1 that was written by T2.If T2 rollback then a=1 will be rollback to a=2 in DB.But,Now ,T1 has a=1 but in DB table it is changed to a=2. 场景1.如果T1事务从表A1读取由另一个并发事务T2写入的数据。如果在T2回滚的路上,T1获得的数据是无效的.Eg a = 2是原始数据。如果T1读取a =由T2写入的1。如果T2回滚则a = 1将在DB中回滚到a = 2.但是,现在,T1具有= 1但在DB表中它变为a = 2。

Scenario2 .If T1 transaction reads data from table A1.If another concurrent transaction(T2) update data on table A1.Then the data that T1 has read is different from table A1.Because T2 has updated the data on table A1.Eg if T1 read a=1 and T2 updated a=2.Then a!=b. 场景2。如果T1事务从表A1读取数据。如果另一个并发事务(T2)更新表A1上的数据。那么T1已读取的数据与表A1不同。因为T2已更新表A1.Eg上的数据,如果T1读a = 1,T2更新a = 2.然后a!= b。

Scenario 3 .If T1 transaction reads data from table A1 with certain number of rows. 场景3.如果T1事务从表A1读取具有特定行数的数据。 If another concurrent transaction(T2) inserts more rows on table A1.The number of rows read by T1 is different from rows on table A1 如果另一个并发事务(T2)在表A1上插入更多行.T1读取的行数与表A1上​​的行不同

Scenario 1 is called Dirty reads. 场景1称为脏读。

Scenario 2 is called Non-repeatable reads. 场景2称为非可重复读取。

Scenario 3 is called Phantom reads. 场景3称为幻影读取。

So, isolation level is the extend to which Scenario 1, Scenario 2, Scenario 3 can be prevented. 因此,隔离级别是可以防止场景1,场景2,场景3的扩展。 You can obtain complete isolation level by implementing locking.That is preventing concurrent reads and writes to the same data from occurring.But it affects performance .The level of isolation depends upon application to application how much isolation is required. 您可以通过实现锁定来获得完整的隔离级别。这会阻止对同一数据的并发读取和写入。但它会影响性能。隔离级别取决于应用程序对应用程序需要多少隔离。

ISOLATION_READ_UNCOMMITTED :Allows to read changes that haven't yet been committed.It suffer from Scenario 1, Scenario 2, Scenario 3 ISOLATION_READ_UNCOMMITTED :允许读取尚未提交的更改。它受场景1,场景2,场景3的影响

ISOLATION_READ_COMMITTED :Allows reads from concurrent transactions that have been committed. ISOLATION_READ_COMMITTED :允许从已提交的并发事务中读取。 It may suffer from Scenario 2 and Scenario 3. Because other transactions may be updating the data. 它可能会受到场景2和场景3的影响。因为其他事务可能正在更新数据。

ISOLATION_REPEATABLE_READ :Multiple reads of the same field will yield the same results untill it is changed by itself.It may suffer from Scenario 3.Because other transactions may be inserting the data ISOLATION_REPEATABLE_READ :同一字段的多次读取将产生相同的结果,直到它自身更改。它可能会受到场景3的影响。因为其他事务可能正在插入数据

ISOLATION_SERIALIZABLE : Scenario 1,Scenario 2,Scenario 3 never happens.It is complete isolation.It involves full locking.It affets performace because of locking. ISOLATION_SERIALIZABLE :场景1,场景2,场景3永远不会发生。它是完全隔离的。它涉及完全锁定。它因锁定而影响性能。

You can test using 你可以测试使用

public class TransactionBehaviour {
   // set is either using xml Or annotation
    DataSourceTransactionManager manager=new DataSourceTransactionManager();
    SimpleTransactionStatus status=new SimpleTransactionStatus();
   ;


    public void beginTransaction()
    {
        DefaultTransactionDefinition Def = new DefaultTransactionDefinition();
        // overwrite default PROPAGATION_REQUIRED and ISOLATION_DEFAULT
        // set is either using xml Or annotation
        manager.setPropagationBehavior(XX);
        manager.setIsolationLevelName(XX);

        status = manager.getTransaction(Def);

    }

    public void commitTransaction()
    {


            if(status.isCompleted()){
                manager.commit(status);
        } 
    }

    public void rollbackTransaction()
    {

            if(!status.isCompleted()){
                manager.rollback(status);
        }
    }
    Main method{
        beginTransaction()
        M1();
        If error(){
            rollbackTransaction()
        }
         commitTransaction();
    }

}

You can debug and see the result with different values for isolation and propagation. 您可以调试并查看具有不同隔离和传播值的结果。


#3楼

Enough explanation about each parameter is given by other answers; 其他答案给出了对每个参数的充分解释; However you asked for a real world example, here is the one that clarifies the purpose of different propagation options: 但是你要求一个真实世界的例子,这里是澄清不同传播选项目的的例子:

Suppose you're in charge of implementing a signup service in which a confirmation e-mail is sent to the user. 假设您负责实施注册服务 ,其中向用户发送确认电子邮件。 You come up with two service objects, one for enrolling the user and one for sending e-mails, which the latter is called inside the first one. 您提出了两个服务对象,一个用于注册用户,另一个用于发送电子邮件,后者在第一个内部调用。 For example something like this: 例如这样的事情:

/* User DAO */
@Transactional(Propagation=MANDATORY)
class UserDAO{
 // some CRUD methods
}

You may have noticed that the second service is of propagation type REQUIRES_NEW and moreover chances are it throws an exception (SMTP server down ,invalid e-mail or other reasons).You probably don't want the whole process to roll-back, like removing the user information from database or other things; 您可能已经注意到第二个服务的传播类型为REQUIRES_NEW ,而且它可能会抛出异常(SMTP服务器关闭,无效的电子邮件或其他原因)。您可能不希望整个过程回滚,如从数据库或其他东西中删除用户信息; therefore you call the second service in a separate transaction. 因此,您在单独的事务中调用第二个服务。

Back to our example, this time you are concerned about the database security, so you define your DAO classes this way: 回到我们的示例,这次您关注数据库安全性,因此您可以通过以下方式定义DAO类:

 /* User DAO */ @Transactional(Propagation=MANDATORY) class UserDAO{ // some CRUD methods } 

Meaning that whenever a DAO object, and hence a potential access to db, is created, we need to reassure that the call was made from inside one of our services, implying that a live transaction should exist; 这意味着每当创建DAO对象并因此创建对db的潜在访问时,我们需要确保调用是从我们的一个服务内部进行的,这意味着应该存在实时事务; otherwise an exception occurs.Therefore the propagation is of type MANDATORY . 否则会发生异常。因此传播的类型为MANDATORY


#4楼

Transaction Isolation and Transaction Propagation although related but are clearly two very different concepts. 事务隔离和事务传播虽然相关但显然是两个非常不同的概念。 In both cases defaults are customized at client boundary component either by using Declarative transaction management or Programmatic transaction management . 在这两种情况下,默认值都是通过使用声明式事务管理程序化事务管理在客户端边界组件上自定义的。 Details of each isolation levels and propagation attributes can be found in reference links below. 每个隔离级别和传播属性的详细信息可以在下面的参考链接中找到。

Transaction Isolation 交易隔离

For given two or more running transactions/connections to a database, how and when are changes made by queries in one transaction impact/visible to the queries in a different transaction. 对于给定的两个或多个正在运行的事务/数据库连接,一个事务中的查询所做的更改如何以及何时对另一个事务中的查询产生影响/可见。 It also related to what kind of database record locking will be used to isolate changes in this transaction from other transactions and vice versa. 它还涉及将使用何种数据库记录锁定来隔离此事务中的更改与其他事务,反之亦然。 This is typically implemented by database/resource that is participating in transaction. 这通常由参与事务的数据库/资源​​实现。

.

Transaction Propagation 交易传播

In an enterprise application for any given request/processing there are many components that are involved to get the job done. 在任何给定请求/处理的企业应用程序中,有许多组件可以完成工作。 Some of this components mark the boundaries (start/end) of a transaction that will be used in respective component and it's sub components. 其中一些组件标记将在各个组件及其子组件中使用的事务的边界(开始/结束)。 For this transactional boundary of components, Transaction Propogation specifies if respective component will or will not participate in transaction and what happens if calling component already has or does not have a transaction already created/started. 对于组件的此事务边界,Transaction Propogation指定相应组件是否将参与事务以及如果调用组件已经或者没有已创建/已启动的事务会发生什么。 This is same as Java EE Transaction Attributes. 这与Java EE Transaction Attributes相同。 This is typically implemented by the client transaction/connection manager. 这通常由客户端事务/连接管理器实现。

Reference: 参考:


#5楼

I have run outerMethod , method_1 and method_2 with different propagation mode. 我使用不同的传播模式运行outerMethodmethod_1method_2

Below is the output for different propagation mode. 以下是不同传播模式的输出。

  • Outer Method 外部方法

     @Transactional @Override public void outerMethod() { customerProfileDAO.method_1(); iWorkflowDetailDao.method_2(); } 
  • Method_1 Method_1

     @Transactional(propagation=Propagation.MANDATORY) public void method_1() { Session session = null; try { session = getSession(); Temp entity = new Temp(0l, "XXX"); session.save(entity); System.out.println("Method - 1 Id "+entity.getId()); } finally { if (session != null && session.isOpen()) { } } } 
  • Method_2 Method_2

     @Transactional() @Override public void method_2() { Session session = null; try { session = getSession(); Temp entity = new Temp(0l, "CCC"); session.save(entity); int i = 1/0; System.out.println("Method - 2 Id "+entity.getId()); } finally { if (session != null && session.isOpen()) { } } } 
      • outerMethod - Without transaction outerMethod - 没有事务
      • method_1 - Propagation.MANDATORY) - method_1 - Propagation.MANDATORY) -
      • method_2 - Transaction annotation only method_2 - 仅限交易注释
      • Output: method_1 will throw exception that no existing transaction 输出:method_1将抛出没有现有事务的异常
      • outerMethod - Without transaction outerMethod - 没有事务
      • method_1 - Transaction annotation only method_1 - 仅限交易注释
      • method_2 - Propagation.MANDATORY) method_2 - Propagation.MANDATORY)
      • Output: method_2 will throw exception that no existing transaction 输出:method_2将抛出没有现有事务的异常
      • Output: method_1 will persist record in database. 输出:method_1将在数据库中保留记录。
      • outerMethod - With transaction outerMethod - 使用事务
      • method_1 - Transaction annotation only method_1 - 仅限交易注释
      • method_2 - Propagation.MANDATORY) method_2 - Propagation.MANDATORY)
      • Output: method_2 will persist record in database. 输出:method_2将在数据库中保留记录。
      • Output: method_1 will persist record in database. 输出:method_1将在数据库中保留记录。 -- Here Main Outer existing transaction used for both method 1 and 2 - 此处主外部现有事务用于方法1和2
      • outerMethod - With transaction outerMethod - 使用事务
      • method_1 - Propagation.MANDATORY) - method_1 - Propagation.MANDATORY) -
      • method_2 - Transaction annotation only and throws exception method_2 - 仅限事务注释并抛出异常
      • Output: no record persist in database means rollback done. 输出:数据库中没有记录持续存在意味着回滚完成。
      • outerMethod - With transaction outerMethod - 使用事务
      • method_1 - Propagation.REQUIRES_NEW) method_1 - Propagation.REQUIRES_NEW)
      • method_2 - Propagation.REQUIRES_NEW) and throws 1/0 exception method_2 - Propagation.REQUIRES_NEW)并抛出1/0异常
      • Output: method_2 will throws exception so method_2 record not persisted. 输出:method_2将抛出异常,因此method_2记录不会持久化。
      • Output: method_1 will persist record in database. 输出:method_1将在数据库中保留记录。
      • Output: There is no rollback for method_1 输出:method_1没有回滚

#6楼

Isolation level defines how the changes made to some data repository by one transaction affect other simultaneous concurrent transactions, and also how and when that changed data becomes available to other transactions. 隔离级别定义了一个事务对某些数据存储库所做的更改如何影响其他并发并发事务,以及这些更改后的数据如何以及何时可用于其他事务。 When we define a transaction using the Spring framework we are also able to configure in which isolation level that same transaction will be executed. 当我们使用Spring框架定义事务时,我们还能够配置将在哪个隔离级别执行相同的事务。

@Transactional(isolation=Isolation.READ_COMMITTED)
public void someTransactionalMethod(Object obj) {

}

READ_UNCOMMITTED isolation level states that a transaction may read data that is still uncommitted by other transactions. READ_UNCOMMITTED隔离级别指出事务可能读取其他事务仍未提交的数据。

READ_COMMITTED isolation level states that a transaction can't read data that is not yet committed by other transactions. READ_COMMITTED隔离级别指出事务无法读取其他事务尚未提交的数据。

REPEATABLE_READ isolation level states that if a transaction reads one record from the database multiple times the result of all those reading operations must always be the same. REPEATABLE_READ隔离级别指出,如果事务多次从数据库中读取一条记录,则所有这些读取操作的结果必须始终相同。

SERIALIZABLE isolation level is the most restrictive of all isolation levels. SERIALIZABLE隔离级别是所有隔离级别中最严格的。 Transactions are executed with locking at all levels (read, range and write locking) so they appear as if they were executed in a serialized way. 事务在所有级别执行锁定(读取,范围和写入锁定),因此它们看起来好像是以序列化方式执行的。

Propagation is the ability to decide how the business methods should be encapsulated in both logical or physical transactions. 传播是决定如何在逻辑或物理事务中封装业务方法的能力。

Spring REQUIRED behavior means that the same transaction will be used if there is an already opened transaction in the current bean method execution context. Spring REQUIRED行为意味着如果当前bean方法执行上下文中已经打开的事务,将使用相同的事务。

REQUIRES_NEW behavior means that a new physical transaction will always be created by the container. REQUIRES_NEW行为意味着容器将始终创建新的物理事务。

The NESTED behavior makes nested Spring transactions to use the same physical transaction but sets savepoints between nested invocations so inner transactions may also rollback independently of outer transactions. NESTED行为使嵌套的Spring事务使用相同的物理事务,但在嵌套调用之间设置保存点,因此内部事务也可以独立于外部事务回滚。

The MANDATORY behavior states that an existing opened transaction must already exist. MANDATORY行为表明现有已打开的事务必须已存在。 If not an exception will be thrown by the container. 如果不是,容器将抛出异常。

The NEVER behavior states that an existing opened transaction must not already exist. NEVER行为表明现有的已打开事务必须不存在。 If a transaction exists an exception will be thrown by the container. 如果存在事务,则容器将抛出异常。

The NOT_SUPPORTED behavior will execute outside of the scope of any transaction. NOT_SUPPORTED行为将在任何事务的范围之外执行。 If an opened transaction already exists it will be paused. 如果已打开的交易已存在,则会暂停。

The SUPPORTS behavior will execute in the scope of a transaction if an opened transaction already exists. 如果已打开的事务已存在,则SUPPORTS行为将在事务范围内执行。 If there isn't an already opened transaction the method will execute anyway but in a non-transactional way. 如果没有已经打开的事务,该方法将以任何方式执行,但是以非事务方式执行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值