【问题标题】:Concurrent write-only transactions并发只写事务
【发布时间】:2013-03-08 03:03:40
【问题描述】:

datastore documentation 说:

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

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

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

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

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

从这些测试中,我得出结论,beginTransactionput 都不能保证执行“初始检查”,我需要支付 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();
}

【问题讨论】:

  • 有一分钟我以为这个问题是关于只写数据库的......我有一个非常高性能的数据库我要卖给你:)

标签: java google-app-engine google-cloud-datastore


【解决方案1】:

从某种意义上说,你是对的。 (MVCC) 在事务观察到可变数据快照的第一个事件之前,一致性不需要时间戳。

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-07
    • 2011-07-05
    • 2016-11-03
    • 2011-10-18
    • 2012-10-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多