Spring @Transactional – 隔离,传播

问题:

有人可以通过真实世界的例子解释@Transactional注释中的隔离传播参数。基本上何时以及为什么我应该选择更改其默认值。

回答:

好的问题,虽然不是一个微不足道的回答。
 Propagation
定义交易如何相互关联。常用选项

  •  Required:代码将始终在事务中运行。创建新的事务或重用一个(如果可用)。
  •  Requires_new:代码将始终在新的事务中运行。暂停当前​​交易(如果存在)。

 Isolation
定义事务之间的数据合同。

  •  Read Uncommitted:允许脏读
  •  Read Committed:不允许脏读
  •  Repeatable Read:如果一行在相同的transaciton中读取两次,结果将始终是相同的
  •  Serializable:执行序列中的所有事务

不同级别在多线程应用程序中具有不同的性能特征。我想如果您了解dirty reads概念,您将可以选择一个很好的选择。
示例可能发生脏读

  thread 1   thread 2      
      |         |
    write(x)    |
      |         |
      |        read(x)
      |         |
    rollback    |
      v         v 
           value (x) is now dirty (incorrect)

所以一个理智的默认(如果这样可以声称)可以是Read Comitted,它只允许你读取已经被其他正在运行的事务所匹配的值,结合传播级别Required。那么你可以从那里工作,如果你的应用程序有其他需求。
一个实际的例子,当进入provideService例程并在离开时完成新常事务。

public class FooService {
    private Repository repo1;
    private Repository repo2;

    @Transactional(propagation=Propagation.REQUIRES_NEW)
    public void provideService() {
        repo1.retrieveFoo();
        repo2.retrieveFoo();
    }
}

如果事务在进入例程时已经打开,我们是否使用Required而不是事务will remain open
还要注意,rollback的结果可能不同,因为几个执行可能参与相同的事务。
我们可以通过测试轻松地验证行为,并查看结果如何随传播水平而不同

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:/fooService.xml")
public class FooServiceTests {

    private @Autowired TransactionManager transactionManager;
    private @Autowired FooService fooService;

    @Test
    public void testProvideService() {
        TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());
        fooService.provideService();
        transactionManager.rollback(status);
        // assert repository values are unchanged ... 
}

具有传播水平

  •  Requires new我们预计fooService.provideService()已经NOT回滚,因为它创建了自己的子事务。
  •  Required我们预计一切都会回滚,后备存储不变。

 
 
Code问答: http://codewenda.com/topics/python/
Stackoverflow: Spring @Transactional – isolation, propagation

*转载请注明本文链接以及stackoverflow的英文链接

发表评论

电子邮件地址不会被公开。 必填项已用*标注

− 1 = 2