SyntaxHighlighter

2012年12月2日日曜日

Google App Engine Python NDB を使ってみた。(7)


NDB Transactions

トランザクションとは一連のオペレーションのセットについて完全に成功かまたは完全に失敗のどちらかにする制御のことである。アプリケーションは複数の計算とオペレーションを一つのトランザクションで行う事が出来る。NDBのAsynchronous APIを使用すると、独立している処理であれば、複数のトランザクションを同時に管理する事が出来る。Synchronous APIは@ndb.transactional()デコレータを使用する事によって簡単にTransactionを制御できる。
競合が発生した場合は、失敗するが、NDBはその失敗したトランザクションを何回か自動的にリトライを行う。従って、その関数はリトライによって複数回呼び出される事がある。リトライの回数はデフォルトで3回である。もしそれでもトランザクションが失敗する場合は、NDBがTransactionFailedErrorを送出する。リトライ回数はtransactional()のretries=Nで設定することが出来る。リトライ回数を0にすると、それは一回だけ試みる事になり、リトライは行わない。リトライ回数のNはトランザクションが試みるであるトータルのN+1回の事である。
トランザクションでは、先祖クエリだけを許している。デフォルトでは、トランザクションは同じエンティティグループに所属するエンティティにのみ作用する。(同じ先祖キーを持つエンティティ達)

また、xg=Trueを設定することで、cross-group("XG")transactionsも使う事が出来る(最大5エンティティグループまで)
もし関数が例外を送出した場合はトランザクションは即時に中断され、NDBはそれを見れるようにする為にもう一度例外を送出する。暗黙にトランザクションを失敗されるにはndb.Rollback例外を送出することで、可能である。(関数の戻り値はNoneになる)これはリトライの機構は持っていない。

常にトランザクション内の処理にしたくない場合もあるが、代わりにデコレート関数の@ndb.transactionalの代わりにcallback関数のndb.transaction()を使う事ができる。

コードがトランザクション内で実行されているかどうかをテストする場合はin_transaction()関数を使えば可能である。

関数が呼びだされた時のトランザクションの振る舞いをどのようにしたら良いかを指定する事が出来る。@ndb.non_transactionalデコレータを指定するとトランザクション内で実行しない方がいい処理となり、トランザクション内で呼び出された場合は、トランザクション外で実行される事になる。@ndb.transactionalデコレータとndb.transaction関数にpropagationキーワード引数をもった関数がある。例えば、関数が呼び出された場合に新しく、独立したトランザクションにしたい場合は、デコレータを下記のようにする。
propagationについては[Context Options and Transaction Options]にリストアップされている。

トランクションの振る舞いとNDBのキャッシュの振る舞いはどのようになるか分からない場合に混乱を招く事がある。例えば、エンティティをトランザクション内で更新しているが、コミットしていない場合に、NDBのキャッシュ上は更新されているが、Datastoreでは更新されていないのである。

今回は、トランザクションについて紹介した。
トランザクションの振る舞いをデコレータで制御できるのは便利である。

次回は、NDB Administrationについて。