【问题标题】:Inconsistent Transaction behavior in Appengine Local Datastore?Appengine 本地数据存储中的事务行为不一致?
【发布时间】:2012-03-09 05:26:57
【问题描述】:

Appengine 文档对数据存储区中的事务这样说: http://code.google.com/appengine/docs/java/datastore/transactions.html#Isolation_and_Consistency

In a transaction, all reads reflect the current, consistent state of the 
Datastore at the time the transaction started. This does not include
previous puts and deletes inside the transaction. Queries and gets inside
a transaction are guaranteed to see a single, consistent snapshot of the
Datastore as of the beginning of the transaction.

考虑到这一点,我创建了以下两个单元测试来测试它(针对本地数据存储)。我希望下面的两个测试都能通过。但是,只有“test1”通过,而“test2”失败。唯一的区别是在“test1”中提交了 tx1。

这是本地数据存储中的错误、对 GAE 文档的误解,还是我的单元测试中的错误?还是别的什么?

谢谢!

@Test(expected = EntityNotFoundException.class)
public void test1() throws EntityNotFoundException {
    DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();

    // Create 2 Transactions...
    Transaction txn1 = datastore.beginTransaction();
    Transaction txn2 = datastore.beginTransaction();

    try {
        Key entityWithStringKey = KeyFactory.createKey("TestEntity", "test");
        Entity entityWithString = new Entity(entityWithStringKey);
        datastore.put(txn1, entityWithString);

        entityWithString = datastore.get(txn2, entityWithStringKey);
        // The above should throw EntityNotFoundException
        assertNull(entityWithString);
    }
    finally {
        if (txn1.isActive()) {
        txn1.rollback();
    }

    if (txn2.isActive()) {
            txn2.rollback();
    }
}


@Test(expected = EntityNotFoundException.class)
public void test2() throws EntityNotFoundException {
    DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();

    // Create 2 Transactions...
    Transaction txn1 = datastore.beginTransaction();
    Transaction txn2 = datastore.beginTransaction();

    Key entityWithStringKey = KeyFactory.createKey("TestEntity", "test");

    try {
        Entity entityWithString = new Entity(entityWithStringKey);
        datastore.put(txn1, entityWithString);
        txn1.commit();
    } finally {

    if (txn1.isActive()) {
        txn1.rollback();
    }
    }

    try {
        Entity entityWithString = datastore.get(txn2, entityWithStringKey);
        assertNull(entityWithString);
        // The above should throw EntityNotFoundException
    } 
    finally {
        if (txn2.isActive()) {
            txn2.rollback();
        }
    }
}

【问题讨论】:

  • test1中没有commit()

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


【解决方案1】:

我怀疑当您调用 datastore.beginTransaction 时事务实际上并没有开始 - 它在事务第一次到达数据库时开始 - 这将是最大限度地减少数据库端锁定的最佳方式。

在测试 2 中,您可以尝试在 txn2 上的 txn1.commit() 之前添加一个额外的 get()。然后第二个 get()(您当前执行 txn2 获取的地方)应该返回 null。

【讨论】:

  • 是的,您的怀疑是正确的。在提交第一个事务之前对第二个事务执行 get() 似乎会启动数据存储中的实际事务。我猜这种行为在实际的 Datastore 上是相同的,但不是 100% 确定。感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-11-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-02
  • 1970-01-01
  • 2014-04-07
相关资源
最近更新 更多