MySQLとPHP+Propel 1.3を使用しているときに、同時実行の問題が発生しているようです。以下は、Propelオブジェクトの「保存」メソッドの小さな例です。
public function save(PropelPDO $con = null) {
$con = Propel::getConnection();
try {
$con->beginTransaction();
sleep(3); // ignore this, used for testing only
parent::save($con);
$foo = $this->getFoo(); // Propel object, triggers a SELECT
// stuff is happening here...
$foo->save($con);
$con->commit();
} catch (Exception $e) {
$con->rollBack();
throw $e;
}
}
問題は$fooオブジェクトです。非常に短い時間で、サンプルメソッドの2つの呼び出しを次々に取得するとします。場合によっては、2番目のトランザクションが$foo...を読み取る場合
$foo = $this->getFoo();
...最初のトランザクションがそれを保存する機会を得る前に...
$foo->save($con);
...2番目のトランザクションによって読み取られた$fooは古くなり、悪いことが起こります。
Fooオブジェクトが格納されているテーブルを強制的にロックして、最初のトランザクションが作業を終了した後にのみ後続のトランザクションがそこから読み取ることができるようにするにはどうすればよいですか?
編集:コンテキストはWebアプリケーションです。要するに、場合によっては、最初のリクエストでデータの変更を行いたいことがあります(これは、$ fooのフェッチと保存の間に発生します)。以降のすべてのリクエストで変更を行うことはできません。変更が発生するかどうかは、フェッチされた$ fooの状態(テーブルの行属性)によって異なります。2つのトランザクションが同じ$fooをフェッチする場合、変更が2回発生し、問題が発生します。