我正在编写Google App Engine Golang应用程序。在Datastore Transaction documentation中,有一个注释:



这使我相信,如果事务返回 ErrConcurrentTransaction ,则意味着数据存储区最终将完成事务。但是,阅读RunInTransaction可以看到一条注释:



看来 ErrConcurrentTransaction 是RunInTransaction函数的失败状态,这意味着事务将永远不会提交。

那是什么呢?如果RunInTransaction返回 ErrConcurrentTransaction ,我的代码应该假定什么?交易成功了吗?将来会成功吗?还是失败了?

最佳答案

具体方案。考虑以下代码段:

err := datastore.RunInTransaction(c, func(c appengine.Context) error {
    var err1 error
    count, err1 = inc(c, datastore.NewKey(c, "Counter", "singleton", 0, nil))
    return err1
}, nil)
// Here, if err is anything other than nil, the datastore-specific
// operations didn't commit to the datastore.

当运行此代码段时,这是一种可能的情况:
  • RunInTransaction启动。它calls the provided function
  • 在该函数中,inc()操作返回nil。
  • RunInTransaction收到该结果,并尝试完成提交。但是由于某种原因,它失败了。 (Where it can fail.),因此RunInTransaction从数据存储区接收ErrConcurrentTransaction。
  • RunInTransaction tries again。它调用提供的函数。
  • 在该函数中,inc()操作返回nil。
  • RunInTransaction收到该结果,并尝试完成提交。但是由于某种原因,它再次失败了。嘿,也许很忙。
  • RunInTransaction再耐心尝试一次该功能。
  • 在该函数中,inc()操作返回nil。
  • RunInTransaction收到该结果,并尝试完成提交。这次,基础数据存储区允许提交。欢呼!
  • RunInTransaction将nil返回给其调用方。

  • 因此,在这种情况下,您的应用程序会观察到ErrConcurrentTransactions。您阅读的第一条注释是有关整个系统的一般注释:总体而言,您的程序可能会遇到ErrConcurrentTransactions。但这并不意味着您编写的代码将直接接触ErrConcurrentTransaction。您的代码可能根本看不到此错误。但是RunInTransaction代表您的代码运行,并且RunInTransaction可能会看到该错误。但是事务仍然可以继续进行,因为RunInTransaction将重播该函数,直到它成功执行或者数据存储足够繁忙以至于它放弃为止。

    如果从RunInTransaction获得零作为最终返回值,则数据存储区操作将通过。但是,如果您获得非零分,他们不会。

    请注意,在上述情况下,作为重试协议(protocol)的一部分,多次调用了RunInTransaction调用的函数。因此,您必须确保传递给RunInTransaction的函数正常,因为在数据存储繁忙时它将尝试使用重试。

    关于google-app-engine - GAE Go-如何处理ErrConcurrentTransaction数据存储区事务错误,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24706487/

    10-11 06:48