简体   繁体   English

ndb 事务中的数据存储实体读取(keys_only)

[英]Datastore Entity read (keys_only) inside ndb transactions

I have a question regarding the datastore entity reads inside a ndb transaction.我有一个关于在 ndb 事务中读取数据存储实体的问题。

I know that when we read an entity inside an ndb transaction, that specific entity gets locked and no other thread can put/update/write the same entity because it will result in a contention error.我知道当我们在 ndb 事务中读取实体时,该特定实体被锁定,并且没有其他线程可以放置/更新/写入同一实体,因为这会导致争用错误。 That totally makes sense.这完全有道理。

However, what happens when we read only the key of an entity instead of the whole entity itself inside the transaction?但是,当我们在事务中只读取实体的键而不是整个实体本身时会发生什么? This can be done by passing keys_only flag as True in ndb.query().fetch() In that case, will the entity again get locked?这可以通过在 ndb.query().fetch()中将 keys_only标志传递为 True 来完成。在这种情况下,实体会再次被锁定吗?

The Datastore documentation for Transaction Locks says: 事务锁数据存储文档说:

Read-write transactions use reader/writer locks to enforce isolation and serializability.读写事务使用读/写锁来强制隔离和可串行化。

And it does not mention any situation with the specifics of the use of keys_only during transactions.并且它没有提到任何在交易期间使用keys_only情况。 So I would assume that the same applies to that situation, which does make sense if you consider that you are still making a read never the less, you are just ignoring the data.所以我认为这同样适用于那种情况,如果你认为你仍然在阅读,这确实是有道理的,你只是忽略了数据。

That being said, maybe this is something that could be improved into Datastore, or even made clear in the documentation.话虽如此,也许这可以改进到 Datastore 中,甚至可以在文档中明确说明。 If you wish, you could consider opening a Feature Request for Google to implement that by following this link .如果您愿意,您可以考虑打开一个功能请求,让 Google 通过点击此链接来实施该功能。

In general, it's better to think of transactions in terms of their guarantee - serializability - rather than their implementation details - in this case, read/write locks.一般来说,最好根据它们的保证——可串行化——而不是它们的实现细节——在这种情况下,读/写锁来考虑事务。 The implementation details (how queries are executed, locking granularity, exactly what gets locked, etc) can potentially change at any time, while the guarantee will not change.实现细节(查询的执行方式、锁定粒度、锁定的确切内容等)可能随时更改,而保证不会更改。

For this specific question, and assuming the current implementation of Firestore in Datastore Mode: to ensure serializability, a keys-only query in a transaction T1 locks the ranges of index entries examined by the query.对于这个特定问题,并假设 Firestore 当前在 Datastore 模式下实现:为了确保可序列化,事务 T1 中的仅键查询会锁定查询检查的索引条目的范围。 If such a query returned a key K for entity E, then an attempt to delete E in a different transaction T2 must remove all of E's index entries, including the one in the range locked by the query.如果这样的查询返回实体 E 的键 K,那么在不同事务 T2 中删除 E 的尝试必须删除 E 的所有索引条目,包括查询锁定范围内的索引条目。 So in this example T1 and T2 require the same locks and one of the two transactions will be delayed or aborted.所以在这个例子中,T1 和 T2 需要相同的锁,两个事务之一将被延迟或中止。

Note that there are other ways for T2 to conflict with T1: it could also be creating a new entity that would match T1's query (which would require writing an index entry in the range locked by T1's query).请注意,T2 还有其他方式与 T1 发生冲突:它还可以创建一个新实体来匹配 T1 的查询(这将需要在 T1 的查询锁定的范围内写入索引条目)。

Finally, if T2 were to update (rather than delete) E in a way that does require any updates to index entries in the range examined by T1's query (eg, if the query is something like 'select * from X where a = 5' and the update to E does not change the value of it's 'a' property) then T1 and T2 will not conflict (this is an optimisation - behaviour would still be correct if these two transactions did conflict, and in fact for "Datastore Native" databases they can conflict).最后,如果 T2 以某种方式更新(而不是删除)E,该方式确实需要对 T1 查询检查的范围内的索引条目进行任何更新(例如,如果查询类似于 'select * from X where a = 5'并且对 E 的更新不会改变它的“a”属性的值)那么 T1 和 T2 不会冲突(这是一种优化 - 如果这两个事务确实发生冲突,行为仍然是正确的,实际上对于“Datastore Native”数据库,它们可能会发生冲突)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM