【问题标题】:Datastore Entity read (keys_only) inside ndb transactionsndb 事务中的数据存储实体读取 (keys_only)
【发布时间】:2021-01-17 22:06:12
【问题描述】:
我有一个关于在 ndb 事务中读取数据存储实体的问题。
我知道,当我们在 ndb 事务中读取实体时,该特定实体会被锁定,并且没有其他线程可以放置/更新/写入同一实体,因为这会导致争用错误。
这完全有道理。
但是,当我们在事务中只读取实体的键而不是整个实体本身时会发生什么?这可以通过在 ndb.query().fetch() 中将 keys_only 标志传递为 True 来完成
在那种情况下,实体会再次被锁定吗?
【问题讨论】:
标签:
google-app-engine
google-cloud-platform
google-cloud-datastore
app-engine-ndb
【解决方案2】:
一般来说,最好根据事务的保证(可串行化)而不是实现细节来考虑事务(在这种情况下,读/写锁)。实现细节(查询的执行方式、锁定粒度、锁定的确切内容等)可能随时更改,而保证不会更改。
对于这个特定的问题,并假设 Firestore 在 Datastore 模式下的当前实现:为确保可序列化,事务 T1 中的仅键查询会锁定查询检查的索引条目的范围。如果这样的查询返回实体 E 的键 K,则在不同事务 T2 中删除 E 的尝试必须删除 E 的所有索引条目,包括查询锁定范围内的条目。所以在这个例子中,T1 和 T2 需要相同的锁,两个事务之一将被延迟或中止。
请注意,T2 与 T1 冲突还有其他方式:它也可能是创建一个与 T1 的查询匹配的新实体(这需要在 T1 的查询锁定的范围内写入一个索引条目)。
最后,如果 T2 更新(而不是删除)E 的方式确实需要对 T1 查询检查的范围内的索引条目进行任何更新(例如,如果查询类似于 'select * from X where a = 5' 并且对 E 的更新不会改变它的 'a' 属性的值),那么 T1 和 T2 不会冲突(这是一种优化 - 如果这两个事务发生冲突,行为仍然是正确的,实际上对于“ Datastore Native”数据库,它们可能会发生冲突)。