BEGIN; SELECT 〜 FOR UPDATE; /* COMMITするまで選択した行をロック*/ UPDATE 〜; COMMIT;
これを CakePHP3 で行うと
ConnectionManager::get('default')->transactional(function () use ($id) { $query = $this->TableClass; $query->find()->where(['id' => $id])->epilog('FOR UPDATE'); $query->first(); //UPDATE などの処理 });
こんな感じ
概要
- トランザクション内で
$query->find()-> ... ->epilog('FOR UPDATE')->first()
を行う- クエリーオブジェクト の find() メソッドでクエリを作成し、epilog() メソッド でクエリの最後に
FOR UPDATE
を追加
- クエリーオブジェクト の find() メソッドでクエリを作成し、epilog() メソッド でクエリの最後に
ハマった事
- Query オブジェクトは遅延評価さるので、下記のコードでは
SELECT 〜 FOR UPDATE
のクエリがまだ実行されておらず、ロックされない。
ConnectionManager::get('default')->transactional(function () use ($id) { $query->find()->where(['id' => $id])->epilog('FOR UPDATE');
- クエリを実行する必要があるので、下記のように
first() メソッド
などを実行して、クエリが実行される条件を満たす必要がある。- See: クエリーの遅延評価
ConnectionManager::get('default')->transactional(function () use ($id) { $query->find()->where(['id' => $id])->epilog('FOR UPDATE')->first();