java - Spring @Transactional - 隔离、传播

标签 java spring transactional isolation propagation

有人可以通过真实示例解释 @Transactional 注释中的 isolationpropagation 参数是什么吗?

基本上什么时候以及为什么我应该选择更改它们的默认值。

最佳答案

好问题,虽然不是一个容易回答的问题。

Propagation

定义事务如何相互关联。常用选项:

  • REQUIRED:代码将始终在事务中运行。创建一个新事务或重复使用一个(如果有)。
  • REQUIRES_NEW:代码将始终在新事务中运行。如果存在,则暂停当前事务。

@Transactional 的默认值是 REQUIRED,这通常是您想要的。

Isolation

定义交易之间的数据契约。

  • ISOLATION_READ_UNCOMMITTED:允许脏读。
  • ISOLATION_READ_COMMITTED:不允许脏读。
  • ISOLATION_REPEATABLE_READ:如果一行在同一个事务中被读取两次,结果总是一样的。
  • ISOLATION_SERIALIZABLE:按顺序执行所有事务。

在多线程应用程序中,不同的级别具有不同的性能特征。我认为如果您了解 脏读 概念,您将能够选择一个好的选项。

默认值可能因不同的数据库而异。例如,对于 MariaDB它是可重复阅读


可能发生脏读的示例:

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

所以一个合理的默认值(如果可以声明的话)可以是 ISOLATION_READ_COMMITTED,它只允许您读取已经被其他正在运行的事务提交的值,结合传播级别 必需的。然后,如果您的应用程序有其他需求,您可以从那里开始工作。


一个实际示例,说明在进入 provideService 例程时始终会创建新事务并在离开时完成:

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

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

如果我们改为使用 REQUIRED,事务 would 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() 被回滚,因为它创建了自己的子事务。

  • REQUIRED:我们希望一切都回滚并且后备存储没有改变。

关于java - Spring @Transactional - 隔离、传播,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8490852/

相关文章:

java - 如何确定选项卡中 fragment 的 XML 布局?

java - hadoop 自定义可写不产生预期的输出

java - 如何区分程序员异常和 JVM 异常

java - 如何从 HashMap 中获取 5 个最高值?

java - 请求映射 - Spring 4 - 不起作用

mysql - Spring多事务回滚

java - 在 Spring 中,服务层总是必须是事务性的吗?

java - Spring Hibernate @Transactional 说明

java - Spring Integration Gateway 中的超时表达式

spring - Spring中是否有像rails中那样通过id进行路由的概念