我们有一个 db 模型,Vote
我们已经使用了一段时间,最近添加了一个 ndb 模型,Score
它代表一个实体的累积分数,基于它的投票。当前Score
是其投票的父节点,因为我们希望它们都在同一个实体组中(因此它们可以在同一个事务中更新)。我一直在尝试使交易能够同时更新Vote
,Score
但它始终失败。这是一些示例代码:
def transaction():
score = self.key_score.get()
vote = db.get(self.key_vote)
# do stuff
score.put()
vote.put()
db.run_in_transaction(transaction)
据我所知(仅限开发服务器),这总是重试四次:
WARNING:root:Transaction collision. Retrying...
WARNING:root:Transaction collision. Retrying...
WARNING:root:Transaction collision. Retrying...
WARNING:root:Transaction collision. Retrying...
ERROR
然后我得到“TransactionFailedError:无法提交事务。请重试。”。
我尝试了一些方法来解决这个问题:
更改获取和放置的顺序 - 我认为可能存在我不理解的实体组锁定问题,但切换获取或放置的顺序并没有改变行为。
异步放置。这实际上是我开始的 - 我所知道的同时放置一个 db 和一个 ndb 模型的唯一方法(我认为这本质上是在幕后放置多个键所做的)。结果相同。
score_future = score.put_async() vote_future = db.put_async(vote) score_future.get_result() vote_future.get_result()
替换
db.run_in_transaction
为ndb.transaction
. 这会在db.get
. 我不确定这里发生了什么 - 看起来一些幕后代码正在db.Key
达到预期的效果ndb.Key
。
有趣的是,如果我删除关系,我可以运行与上面相同的代码parent
,这意味着实体不在同一个实体组中。
那么,是否可以在同一个实体组中同时拥有 db 和 ndb 模型?也许有一种简单的方法可以将 db 模型作为 ndb 或反之亦然?