2月
13
2011
Teeple2で楽観的排他制御を実現するには
投稿者: miztaka, カテゴリ: PHP, Teeple2, tags: java, php, seasar, teeple2概要
「楽観的排他制御」という言葉を初めて目にしたのはJavaフレームワークSeasar2のS2Daoにおいてでした。
それまでの開発ではSELECT FOR UPDATEを多用していた気がしますが、以来ほぼすべてのプロジェクトで「楽観的排他制御」のパターンを用いることにしました。統一的でシンプルな仕様だからです。
ここで言う楽観的排他制御とは
以下のようなしくみを言います。
- 全てのテーブルには version列(int)またはtimestamp列(timestamp)を用意する。(version列のほうがよいと思います。)
- レコードの更新をするときに version列もwhere句に含め、set句にはversion列をインクリメントする。(timestampの場合はtimestampをセット。)
- update件数が0件だったら例外を投げる。
- 上記動作をDBアクセスライブラリ(ORマッパー)が透過的に取り仕切る。(開発者は意識しない。)
Teeple2で実現するには
Teeple2 でこれを実現する方法を解説します。
Teeple2のDBアクセスライブラリ Teeple_ActiveRecordでは、insertおよびupdateの実行前に teeple_activerecord_before_insert, teeple_activerecord_before_update という関数の存在を調べ、存在した場合はこれらを実行した後に insert(update)を実行するようになっています。
このhook関数にはエンティティオブジェクト自身が引数として渡ってくるので、ここでversion列をインクリメントしたり条件を追加することによって楽観的排他制御が実現できるわけです。
例えば以下のようなコードをuser.inc.phpに追加します。
function teeple_activerecord_before_update($obj) { if (property_exists(get_class($obj), 'version') === TRUE) { // 楽観的排他制御 $obj->setConstraint('version', $obj->version); $obj->version += 1; } return; }