GAE でデータストアを扱う場合、トランザクションには縛りがあって、エンティティグループ内でしか1トランザクションとして扱えない。
このエンティティグループというのが曲者で、こいつらは1トランザクションとして作成/更新/削除できるが、データストアとしては分散できないため、あまり大きなエンティティグループを作成するのはよくないらしい。
話は前後するが、このエンティティグループというやつは、DBモデルの親子関係を結ぶことで(つまり共通の親を持つ)ことで作成される(相手へのリファレンスとは別物)。
エンティティグループでないトランザクションは、一度に処理できない。
以下、a,b は同一エンティティグループに属さないため、1トランザクションで処理できない。
class Sample(db.Model):
counter = db.IntegerProperty()
def inc_counter(a, b):
a = Sample(counter=a)
b = Samble(counter=b)
a.put()
b.put()
db.run_in_transaction(inc_counter, 1, 2)
ビックテーブルの性格上、ある程度しょうがないとして推奨例が
http://code.google.com/intl/ja/appengine/docs/python/datastore/keysandentitygroups.htmlにこっそり書いてあります。
- トランザクションに必要なときにだけ、エンティティ グループを使用します。その他のエンティティ間の関係には、ReferenceProperty プロパティと、クエリで使用できる Key 値を使用します。
トランザクション処理が必要ないときは、エンティティグループを使用しないで、リファレンスを使用する。
例外:
トランザクションが必要な場合、エンティティグループとする。
Aさん から Bさん へお金の移動をしたい。でも100万人もユーザーがいる場合、全員をエンティティグループにしたくない。
この場合、Aさん Bさん の親を仮に作成してエンティティグループにし、1トランザクションで実行した後、親エンティティを消せばいいのかな?。ビックテーブルでは親が消えても子のエンティティは存続するし。
簡単に試せそうだけど、面倒くさいので必要になったとき検証します。ぐだぐだ...
「エンティティグループへの加入は、エンティティ生成時のみ」という記述を、何かで見たような気がします
返信削除(ソースが見当たらなくて申し訳ないですが)