为了账号安全,请及时绑定邮箱和手机立即绑定

谷歌云数据存储提交冲突检测

谷歌云数据存储提交冲突检测

Go
哔哔one 2022-08-01 17:05:45
我在数据存储模式下使用 Firestore。我没有使用Google或任何人提供的客户端库,而是通过从库(任何人都可以生成的库)直接与Datastore进行通信。我使用它是因为高级客户端不应该使用实体版本和冲突检测机制。proto grpc我正在执行事务更新并指定冲突检测策略基本版本(每个实体可能包含以前已知的版本)。问题是,当任何实体中存在版本冲突时,整个提交操作会失败吗?如果它没有失败,是否会在数据存储中应用此类提交,并且我不会使用简单的事务回滚调用进行回滚。我是否仍需要通过对数据存储的单独调用在该事务之外实现自己的独立回滚?突变产生承诺并决定下一步该做什么我已经浏览了文档,并且在这个问题上还远远没有完成。这是我唯一发现的东西。https://cloud.google.com/datastore/docs/reference/data/rpc/google.datastore.v1#google.datastore.v1.MutationResult
查看完整描述

1 回答

?
天涯尽头无女友

TA贡献1831条经验 获得超9个赞

数据存储对单个事务中可以完成的内容施加了限制。通常,当存在提交冲突时,并发事务/修改会得到回复。您可以通过启动写入同一文档的两个事务,提交并查看预期行为来重现此情况。

文档

当两个或多个事务同时尝试修改一个或多个公共实体组中的实体时,只有提交其更改的第一个事务才能成功;所有其他的将在提交时失败。由于此设计,使用实体组会限制可以对组中的任何实体执行的并发写入次数。当事务启动时,数据存储通过检查事务中使用的实体组的上次更新时间来使用开放式并发控制。为实体组提交事务后,数据存储会再次检查事务中使用的实体组的上次更新时间。如果自初始检查以来已更改,则会引发异常。

最好的方法是快速重现它并查看确切的行为。问题是,当任何实体中存在版本冲突时,整个提交操作会失败吗?

是的。

包装器将自动重试您的交易。运行事务库的数据存储应能更深入地了解其行为方式。有关详细信息,请查看下面看到的 RunIn 事务,并了解它如何评估事务。Golang

func (c *Client) RunInTransaction(ctx context.Context, f func(tx *Transaction) error, opts ...TransactionOption) (cmt *Commit, err error) {

        ctx = trace.StartSpan(ctx, "cloud.google.com/go/datastore.RunInTransaction")

        defer func() { trace.EndSpan(ctx, err) }()

     

        settings := newTransactionSettings(opts)

        for n := 0; n < settings.attempts; n++ {

     tx, err := c.newTransaction(ctx, settings)

     if err != nil {

     return nil, err

     }

     if err := f(tx); err != nil {

     _ = tx.Rollback()

     return nil, err

     }

     if cmt, err := tx.Commit(); err != ErrConcurrentTransaction {

     return cmt, err

     }

     // Pass this transaction's ID to the retry transaction to preserve

     // transaction priority.

     if !settings.readOnly {

     settings.prevID = tx.id

     }

        }

        return nil, ErrConcurrentTransaction

    }


查看完整回答
反对 回复 2022-08-01
  • 1 回答
  • 0 关注
  • 111 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信