2

数据存储文档说:

为实体组提交事务后,App Engine 会再次检查事务中使用的实体组的上次更新时间。如果它在我们的初始检查后发生了变化,App Engine 会抛出一个异常

new Entity("TestEntity",1)我有三个关于在两个并发事务中执行事务数据存储放置的测试用例。

  • test1:将实体放在第一个事务中,将实体放在第二个事务中,并提交两个事务。该测试在开发服务器和独立单元测试中运行时通过(即抛出ConcurrentModificationException),但在生产服务器中运行时失败(即在不抛出异常的情况下执行)。

  • test2:将实体放在第一个事务中并提交,然后将实体放在第二个事务中并提交。这个测试总是失败。

  • test3:尝试在两个事务中获取(不存在的)实体,然后执行 test2。这个测试总是通过 throw ConcurrentModificationException

从这些测试中,我得出结论,既不beginTransaction也不put保证执行“初始检查”,我需要支付一笔费用以保证交易的完整性。那是对的吗?

@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)在事务观察到可变数据快照的第一个事件之前,一致性不需要时间戳。

想一想:在没有任何读取的情况下改变单个记录的事务怎么会违反一致性?由于它没有发出读取,因此它基本上没有做出任何假设。因此,没有任何假设可以被破坏以导致写-写冲突。

最重要的是,无论如何,您都将获得一致性的安全优势。在您发出第一个事务读取之前,强制执行该一致性根本不需要时间戳。

于 2013-03-08T03:48:09.730 回答