google-app-engine - 应用引擎 : Mechanics of creating a unique entity if it doesn't exist

标签 google-app-engine transactions google-cloud-datastore

我们有一个问题,我们想懒惰地创建一个不存在的实体。关于如何执行此操作的讨论正在进行中,我想澄清一些有关应用程序引擎事务的事情。我会将查询限制为单个实体组交易。

我在示例中使用的是 Go,但我希望代码对于非 Go 程序员来说足够清晰。

我的理解是,在单个实体组上的事务只有在事务期间没有从外部修改实体组时才会成功。指示实体组何时更改的“实体组时间戳”存储在实体组的根实体中。因此在交易期间,当前的“实体组时间戳”被读取,并且只有在交易结束时它没有改变时交易才能成功。

key := datastore.NewKey(c, "Counter", "mycounter", 0, nil)
count := new(Counter)
err := datastore.RunInTransaction(c, func(c appengine.Context) error {
  err := datastore.Get(c, key, count)
  if err != nil && err != datastore.ErrNoSuchEntity {
    return err
  }
  count.Count++
  _, err = datastore.Put(c, key, count)
  return err
}, nil)

在上面的例子中(取自 https://cloud.google.com/appengine/docs/go/datastore/transactions )有两个非错误的情况,我可以看到:

  • Get 成功,计数器上的“实体组时间戳”可用于确保在此事务期间没有其他事务更新计数器。
  • Get 失败并显示 ErrNoSuchEntity,Put 用于首次存储计数器。

在第二种情况下,另一个相同的事务可能正在运行。如果两个事务的 Get 都返回 ErrNoSuchEntity,数据存储如何确保只有一个 put 成功?我希望数据存储中没有“实体组时间戳”来进行测试吗?

交易是否知道它需要测试计数器是否存在才能使 Put 和整个交易成功?

在这种情况下,两笔交易是否有可能成功,而一笔 Put 会覆盖另一笔?

如果有关于控制此机制的文档或视频等,我很乐意阅读。

最佳答案

要回答您的问题,我们必须深入挖掘开发数据存储的源代码,对我们来说幸运的是它有很好的文档记录,只需看看 LiveTxn._GrabSnapshot :

Gets snapshot for this reference, creating it if necessary.

If no snapshot has been set for reference's entity group, a snapshot is taken and stored for future reads (this also sets the read position), and a CONCURRENT_TRANSACTION exception is thrown if we no longer have a consistent snapshot.

所以边缘情况与您推测的略有不同:两个事务都会创建一个新的时间戳,然后一切都会像往常一样工作。在您提出的情况下,第二笔交易将重试,并且计数器将增加两次。

据我所知,没有关于事务如何工作的深入文档,至少不是这么深,但源代码实际上并不那么读;在这种情况下,您可以跟踪 CONCURRENT_TRANSACTION 错误。

关于google-app-engine - 应用引擎 : Mechanics of creating a unique entity if it doesn't exist,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30233093/

相关文章:

java - Google Cloud Datastore - Java - GQLQuery 游标

java - MaxMind GeoIP2(版本 2.7.0)在 GAE 中不可用

java - 将 csv 文件上传到 appengine

google-app-engine - GCloud 部署到 App Engine 响应错误请求

http - 创建要通过 Google App Engine 提供的 tar 文件

google-app-engine - JPA 和应用引擎中的子实体身份(危机)

java - 一个 JDBC 连接中可以有两个并发事务吗?

sql-server - 将 bcp 放入带有另一个 sql 语句的事务中

jpa - 什么时候刷新和清除提交?

macros - 在 Clojure 中使用宏