2

@Stateless残りのリソースで WildFly 9.0.2 に繰り返し不可の読み取り分離レベルを実装しています

  1. スレッド A はAccountエンティティを読み取り、残高を出力してから、他の作業 (スリープ) を実行します。
  2. スレッド B が入ってきて、同じAccountエンティティを読み取り、残高を出力してメソッドを介して残高を計算しcalculateBalance()、エンティティを更新します。エンティティを再度読み取り、残高を出力します。
  3. 次に、スレッド A がエンティティを読み取り、残高を出力します。

Non-Repeatable 読み取りレベルに関する私の理解によれば、スレッド B は、スレッド A が完全に終了するまでブロックする必要があります (トランザクションを終了する/ステートレス レスト リソース)。

印刷物は次のとおりです。

  • スレッド A: printBalance=500
  • スレッド B: printBalance=500
  • スレッド B: printBalance=600
  • スレッド A: printBalance=500

そのことから、スレッド A がまだビジーであっても、スレッド B がブロックされておらず、実行が許可されていることがわかります。

以下はコードです:

    @GET
    @Path("/{accountId}/{threadName}")
    public Response calculcateBalance(@PathParam("accountId") Long accountId, @PathParam("threadName") String threadName) {

        Account account = em.find(Account.class, accountId);
        printBalance(account,threadName);

        if ("ThreadA".equals(threadName)) {
            sleepSeconds(10);
        } else if ("ThreadB".equals(threadName)) {
            account.calculateBalance();
            em.merge(account);
        }

    account = em.find(Account.class, accountId);
    printBalance(account,threadName);

    return Response.ok().build();
}

分離レベルを Serializable に変更すると、すべてがブロックされます。

Non-repeatable read についての私の理解は間違っていますか? スレッド A が終了するまでスレッド B をブロックしないでください。

4

1 に答える 1

2

基盤となるデータベース システムによって異なります。デフォルトで 2PL を使用する SQL Server を使用している場合、スレッド A はその行の読み取り時に共有ロックを取得し、スレッド B はその行の書き込みを防止します (スレッド A が共有ロックを解放するまで)。

Oracle、PostgreSQL、および MySQL は MVCC を使用し、反復可能読み取りはロックを使用しません。これは、リーダーがライターをブロックせず、ライターがリーダーをブロックしないためです。MVCC では、異常が検出され、スレッド B がその行を変更すると、スレッド A はその変更を検出し、そのトランザクションを中止します。

したがって、MVCC では、異常を防止するのではなく検出します。

于 2016-01-22T16:59:59.147 に答える