質問: 【環境】 フレームワーク:Zend Framework 1.12 DB:mysql 5.6.10-log ストレージエンジン:InnoDB 1.2.10 【問題】 データの移行処理を開発中に、移行後のデータの件数をカウントしたら0件になっていました。 このデータの移行処理は、X1の1000件のデータをトランザクションを切って、X2に登録する処理をX1の全データ分行います。 トランザクションの最初では、移行処理が完了しているかを判定するために、X1、X2の件数を取得して一致していたら完了という処理を行っています。 問題は、トランザクション中にX2にinsertを行いcommitした後、次のトランザクションでX2のデータをカウントすると、0件に成ってしまうことです。 【処理のイメージ】 1. トランザクション1 a. X1、X2の件数を取得、移行が完了したかを判定 b. X1 → X2 1000件登録 2. トランザクション2 a. X1、X2の件数を取得、移行が完了したかを判定 →X2のデータをcountすると0件 b. X1 → X2 1000件登録 【質問】 sleepで1秒ほど待てば、このX2のデータを取得できるようになったので、おそらくトランザクションでinsertしたレコードに排他ロックがかかっており、カウントできなかったのではと推測しています。 そこで質問なのですが、前のトランザクションが終了し、insertしたデータの排他ロックが解除されたことをPHP上、または、mysql上で知る方法はあるでしょうか?
回答: 状態を知るということであれば、結局リトライする必要があるので、以下のような方法はどうでしょうか。 トランザクション1で排他用のテーブルをfor update付きでselectし、トランザクション2の開始時にその排他用テーブルをselectするようにしておけば、トランザクション1のコミットが完了した時点で、トランザクション2のselectが完了するようになります。 質問そのものに対する回答ではありませんが、トランザクション1とトランザクション2は必ずセットで行われるものなら、分割していること自体が適切ではありませんね。 一つのトランザクションとして行えば済む話ではないでしょうか。 トランザクションバッファ等の容量制限で分割しているということなら、処理件数で分割するのが好ましいと思います。