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
}
- 1 回答
- 0 关注
- 111 浏览
添加回答
举报