当多个实例并行命中@Transactional注释方法时会发生什么?

时间:2014-02-15 22:08:53

标签: java spring transactions

如果我错了,请纠正我。

我遇到的问题是我的交易没有保存到数据库中,而且正在进行某种竞争,这会导致数据搞砸。该应用程序由多个实例并行命中。我使用了@Transactional,我知道这是与数据库进行的事务,并且在方法返回时提交事务。

问题是,通过多个实例打击它仍然会保持每个命中事件的这一个事务,或者它不处理这种情况,数据会因为竞争而搞砸了吗?

是否可以针对给定条件建议解决方案?

2 个答案:

答案 0 :(得分:3)

@Transactional与同步无关。它只是确保您的流程成功或失败。每次打击都有自己的流程和自己的成功或失败。

我猜你正在经历的是由于共享数据的使用。

例如。如果您的班级Foo如下所示:

public class Foo {
    private static boolean flag = true;

    @Transactional
    public void doSomething() {
        flag = false;
    }
}

在这种情况下,您拥有多个Foo个实例并不重要,因为它们都使用相同的flag

另一种情况是,如果您有一个Foo实例(如果您使用类似Spring之类的内容非常常见)并且您为此实例更改了数据。您可以查看相同的Foo示例,只需从static移除flag

public class Foo {
    private boolean flag = true;

    @Transactional
    public void doSomething() {
        flag = false;
    }
}

在任何一种情况下,您都需要以某种方式同步数据更改。它与@Transactional无关。

答案 1 :(得分:2)

该事务是数据库事务,并且行为依赖于数据库引擎,但它通常以这种方式工作:

  1. 线程输入方法。
  2. 线程输入相同或任何其他事务方法。 不会阻止,因为@Transactional 与同步无关
  3. 一个线程执行阻止数据库资源的任何查询。例如。 SELECT * FROM MYTABLE FOR UPDATE;
  4. 另一个线程尝试执行任何需要相同数据库资源的内容。例如。 UPDATE MYTABLE SET A = A + 1; 并阻止
  5. 在步骤 3 上获得锁定的线程完成了成功进行隐式提交的事务方法,或者无法进行隐式回滚。< / LI>
  6. 被阻止的线程唤醒并继续,因为它现在可以获取被锁定的资源。