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 のエンティティグループに適用できます。祖先クエリはクエリを 1 つのエンティティ グループに制限し、1 つの XG トランザクションでこれら 25 のエンティティ グループ内でクエリを実行できます。

親のないトランザクション クエリでは、アプリケーション内のすべてのエンティティ グループが含まれる可能性があり、すべてがロックされるため、代わりにエラー メッセージが表示されます。

アプリ エンジンでは、通常、id が単調に増加するのを避けようとします。自動割り当てのものは、101、10001、10002 などのようになります。ID を単調に増やす必要があることがわかっていて、それがパフォーマンスの面でうまくいく場合は、次のようにします。

  1. key_name の使用と直接検索を有効にするために、ある種の userId のモデル表現を用意します。

  2. トランザクション外で userId を照会し、最上位の候補 ID を取得します

  3. トランザクションで get_or_insert; を実行します。UserId.get_by_key_name(candidateid+1) を検索します。すでに存在し、別のユーザーを指している場合は、+2 などで再試行し、空いているユーザーを見つけて作成し、同時にユーザーのユーザー ID 属性を更新します。

UserId+User を更新する XG トランザクションが遅すぎる場合は、おそらく (XG ではなく) トランザクションで UserId+task を作成し、後で実行中のタスクに UserId と User を関連付けさせます。または、UserId の作成をシリアル化できる単一のバックエンドで、シーケンスの穴を回避し、1 秒あたり 50 回の作成などを再試行する場合は、おそらく put_async を許可します。

userName を key_name として使用できる場合は、クエリの代わりに直接ルックアップを実行して、処理を高速かつ安価にすることができます。

于 2012-05-29T13:49:03.257 に答える
1

クロスグループトランザクションを使用すると、複数のグループ間でトランザクションを実行できますが、トランザクション内のクエリの禁止は解除されません。トランザクションの外部でクエリを実行し、エンティティのIDを渡す必要があります(そして、クエリで指定された不変条件がまだ保持されていることを確認します)-または、Shayが示唆するように、IDを使用してクエリを実行する必要はありませんそもそも。

于 2012-05-29T01:06:47.993 に答える
1

すべてのデータストア エンティティにはキーがあり、キー (その他の量) には、AppEngine が割り当てる数値 IDまたは指定できる key_name があります。

あなたの場合、ユーザーエンティティで put() を呼び出した後、数値IDを使用できるように見えます: user.key().id() (またはNDBを使用している場合はuser.key.id())これはユーザーごとに一意になります(すべてのユーザーが同じ親を持っている限り、コードでは None です)。

この ID は連続したものではありませんが、一意であることが保証されています。

于 2012-05-29T05:46:42.590 に答える