0

据我了解,@db.transactional(xg=True) 允许跨组进行事务,但是以下代码返回“事务中的查询必须有祖先”。

@db.transactional(xg=True)
def insertUserID(self,userName):
    user = User.gql("WHERE userName = :1", userName).get()
    highestUser = User.all().order('-userID').get()
    nextUserID = highestID + 1 
    user.userID = nextUserID
    user.put()

尽管是跨组事务,您是否需要为每个实体传递密钥?你能帮忙修改这个例子吗?

4

3 回答 3

2

XG 事务最多可应用于25 个实体组。祖先查询将查询限制为单个实体组,您将能够在单个 XG 事务中在这 25 个实体组中进行查询。

没有父级的事务查询可能会包括应用程序中的所有实体组并锁定所有内容,因此您会收到一条错误消息。

在应用引擎中,通常会尝试避免单调增加的 id。自动分配的可能会像 101、10001、10002 等等。如果你知道你需要单调递增的 id 并且它会为你的性能工作,那么如何:

  1. 具有 userId 的某种模型表示以启用 key_name 使用和直接查找

  2. 查询事务外的userId,获取最高的候选id

  3. 在事务中做 get_or_insert; 查找 UserId.get_by_key_name(candidateid+1)。如果已经存在并指向不同的用户,请使用 +2 重试,以此类推,直到找到一个免费的并创建它,同时更新用户的 userid 属性。

If the XG-transaction of updating UserId+User is too slow, perhaps create UserId+task in transaction (not XG), and let the executing task associate UserId and User afterwards. Or a single backend that can serialize UserId creation and perhaps allow put_async if you retry to avoid holes in the sequence and do something like 50 creations per second.

If it's possible to use userName as key_name you can do direct lookup instead of query and make things faster and cheaper.

于 2012-05-29T13:49:03.257 回答
1

跨组事务允许您跨多个组执行事务,但它们不会取消对事务内部查询的禁止。您需要在事务之外执行查询,并将实体的 ID 传入(然后检查查询中指定的任何不变量是否仍然有效) - 或者,正如 Shay 建议的那样,使用 ID,因此您不必进行查询首先。

于 2012-05-29T01:06:47.993 回答
1

每个数据存储实体都有一个键,一个键(其他数量)有一个 AppEngine 分配给它的数字 id您可以给它的 key_name。

在您的情况下,您似乎可以使用数字 ID,在您对用户实体调用 put() 之后,您将拥有: user.key().id() (如果您使用 NDB,则为 user.key.id() )这对于每个用户都是唯一的(只要所有用户都有相同的父级,在您的代码中为 None )。

此 id 不是连续的,但保证是唯一的。

于 2012-05-29T05:46:42.590 回答