中村(次) (2010年11月 5日 14:33) 企画開発部 / MySQL
先日とあるシステムで同一の処理が複数回実行されるという現象が発生しました。 1度しか処理は走らないように実装されているのですが、 なぜか複数実行されてしまっていました。
まず、処理自体はどのようになっているかを説明します。 1.連携ステータスが「未連携」のデータを取得する 2.他システムと連携する処理を実行する 3.連携ステータスを「連携済み」に更新する
上記のように実装していたので、一度しか処理は走らないと思っていましたが、 調べたところ、以下のような現象が発生していました。
連携処理自体はいろいろな処理から実行されます。 そうすると、1のデータ取得処理も同時に実行されてしまうので、 複数回実行されることになります。
3の更新処理が実行されて、初めて連携対象外となるので、 3が実行される前にデータ取得の処理が走ってしまうと、複数連携されることになります。
この問題を解決するために使用したのが、SELECT ~ FOR UPDATE 文です。
1.トランザクション開始 2.SELECT ~ FOR UPDATE 文で連携ステータスが「未連携」のデータを取得する 3.連携ステータスを「連携中」に更新する 4.トランザクション終了 5.他システムと連携する処理を実行 6.連携ステータスを「連携済み」に更新する
上記のようにすると、トランザクションがコミットされるまでは、 データ取得処理もロックされますので、他から呼び出された処理が割り込むことはありません。
MySQL SELECT~FOR UPDATE
中村(次) (2010年11月 5日 14:33)
企画開発部 / MySQL
先日とあるシステムで同一の処理が複数回実行されるという現象が発生しました。
1度しか処理は走らないように実装されているのですが、
なぜか複数実行されてしまっていました。
まず、処理自体はどのようになっているかを説明します。
1.連携ステータスが「未連携」のデータを取得する
2.他システムと連携する処理を実行する
3.連携ステータスを「連携済み」に更新する
上記のように実装していたので、一度しか処理は走らないと思っていましたが、
調べたところ、以下のような現象が発生していました。
連携処理自体はいろいろな処理から実行されます。
そうすると、1のデータ取得処理も同時に実行されてしまうので、
複数回実行されることになります。
3の更新処理が実行されて、初めて連携対象外となるので、
3が実行される前にデータ取得の処理が走ってしまうと、複数連携されることになります。
この問題を解決するために使用したのが、SELECT ~ FOR UPDATE 文です。
1.トランザクション開始
2.SELECT ~ FOR UPDATE 文で連携ステータスが「未連携」のデータを取得する
3.連携ステータスを「連携中」に更新する
4.トランザクション終了
5.他システムと連携する処理を実行
6.連携ステータスを「連携済み」に更新する
上記のようにすると、トランザクションがコミットされるまでは、
データ取得処理もロックされますので、他から呼び出された処理が割り込むことはありません。