2

我们有一个 db 模型,Vote我们已经使用了一段时间,最近添加了一个 ndb 模型,Score它代表一个实体的累积分数,基于它的投票。当前Score是其投票的父节点,因为我们希望它们都在同一个实体组中(因此它们可以在同一个事务中更新)。我一直在尝试使交易能够同时更新VoteScore但它始终失败。这是一些示例代码:

    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:无法提交事务。请重试。”。

我尝试了一些方法来解决这个问题:

  1. 更改获取和放置的顺序 - 我认为可能存在我不理解的实体组锁定问题,但切换获取或放置的顺序并没有改变行为。

  2. 异步放置。这实际上是我开始的 - 我所知道的同时放置一个 db 和一个 ndb 模型的唯一方法(我认为这本质上是在幕后放置多个键所做的)。结果相同。

    score_future = score.put_async()
    vote_future = db.put_async(vote)
    score_future.get_result()
    vote_future.get_result()
    
  3. 替换db.run_in_transactionndb.transaction. 这会在db.get. 我不确定这里发生了什么 - 看起来一些幕后代码正在db.Key达到预期的效果ndb.Key

有趣的是,如果我删除关系,我可以运行与上面相同的代码parent,这意味着实体不在同一个实体组中。

那么,是否可以在同一个实体组中同时拥有 db 和 ndb 模型?也许有一种简单的方法可以将 db 模型作为 ndb 或反之亦然?

4

1 回答 1

5

所有实体在数据存储中看起来都是一样的,无论它们是使用 DB 还是 NDB 创建的。这里的问题是您试图在 API 调用中混合两者;db 在传递 ndb 模型实例时不知道该怎么做。

您需要为 Vote 创建一个与您的 db 模型相同的 NDB 模型 - 或者更好的是,将 Vote 迁移到 NDB 模型 - 并在需要为两种实体类型进行事务的任何代码中使用它。

于 2012-11-09T20:56:00.247 回答