2

データストアのドキュメントには次のように書かれています。

エンティティグループのトランザクションをコミットすると、AppEngineはトランザクションで使用されたエンティティグループの最終更新時刻を再度確認します。最初のチェック以降に変更された場合、AppEngineは例外をスローします

new Entity("TestEntity",1)2つの同時トランザクションでのトランザクションデータストアプットの実行に関する3つのテストケースがあります。

  • test1:エンティティを最初のトランザクションに入れ、エンティティを2番目のトランザクションに入れ、両方のトランザクションをコミットします。このテストはConcurrentModificationException、開発サーバーおよびスタンドアロンの単体テストで実行すると合格(つまり、スロー)しますが、本番サーバーで実行すると失敗(つまり、例外をスローせずに実行)します。

  • test2:エンティティを最初のトランザクションに入れてコミットしてから、エンティティを2番目のトランザクションに入れてコミットします。このテストは常に失敗します。

  • test3:両方のトランザクションで(存在しない)エンティティの取得を試みてから、test2を実行します。このテストは常に。を投げることで合格しConcurrentModificationExceptionます。

これらのテストから、「初期チェックbeginTransaction」が実行されることもput保証もされていないと結論付け、トランザクションの整合性を保証するためにgetを支払う必要があります。あれは正しいですか?

@Test(expected=ConcurrentModificationException.class)
//put1 put2 commit1 commit2
public void test1() {
    DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
    Transaction txn1 = ds.beginTransaction();
    Transaction txn2 = ds.beginTransaction();
    ds.put(txn1,new Entity("TestEntity",1));
    ds.put(txn2,new Entity("TestEntity",1));
    txn1.commit();
    txn2.commit();
}

@Test(expected=ConcurrentModificationException.class)
//put1 commit1 put2 commit2
public void test2()  {
    DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
    Transaction txn1 = ds.beginTransaction();
    Transaction txn2 = ds.beginTransaction();
    ds.put(txn1,new Entity("TestEntity",1));
    txn1.commit();
    ds.put(txn2,new Entity("TestEntity",1)); 
    txn2.commit(); 
}

@Test(expected=ConcurrentModificationException.class)
//get1 get2 put1 commit1 put2 commit2
public void test3() throws InterruptedException, ExecutionException {
    DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
    ds.delete(KeyFactory.createKey("TestEntity", 1));
    Transaction txn1 = ds.beginTransaction();
    Transaction txn2 = ds.beginTransaction();
    Assert.assertNull(getTestEntity(ds, txn1));
    Assert.assertNull(getTestEntity(ds, txn2));
    ds.put(txn1,new Entity("TestEntity",1));
    txn1.commit();
    ds.put(txn2,new Entity("TestEntity",1));
    txn2.commit();
}
4

1 に答える 1

4

あなたはある意味で正しいです。(MVCC) 一貫性は、トランザクションが変更可能なデータのスナップショットを観察する最初のイベントまで、タイムスタンプを必要としません。

考えてみてください: 読み取りを行わずに 1 つのレコードを変更したトランザクションは、どのようにして整合性に違反するのでしょうか? 読み取りを発行しなかったため、基本的には仮定を行いません。したがって、書き込みと書き込みの競合を引き起こす可能性のある仮定はありません。

肝心なのは、何があっても、一貫性のある安全性の利点を得ているということです。その一貫性を強制するには、最初のトランザクション読み取りを発行するまで、タイムスタンプは必要ありません。

于 2013-03-08T03:48:09.730 に答える