これは、この関連する質問から生じました。ここでは、2つのトランザクションを単純なケース(両方が単一の行でのみ動作している)で連続して発生させる方法を知りたいと思いました。SELECT ... FOR UPDATE
両方のトランザクションの最初の行として使用するという回答を得ましたが、これは問題につながります。最初のトランザクションがコミットまたはロールバックされない場合、2番目のトランザクションは無期限にブロックされます。innodb_lock_wait_timeout
変数は、2番目のトランザクションを作成しようとしているクライアントは、「申し訳ありませんが、もう一度やり直してください」と言われるでしょう...しかし、私の知る限り、彼らは次のサーバを再起動するまで再試行されると思いまでの秒数を設定します。そう:
ROLLBACK
トランザクションが永遠にかかっている場合、強制する方法が必ずあるはずです。そのようなトランザクションを強制終了するためにデーモンを使用する必要があります。その場合、そのようなデーモンはどのようになりますか?- 接続がトランザクションによって
wait_timeout
またはinteractive_timeout
トランザクションの途中で強制終了された場合、トランザクションはロールバックされますか?コンソールからこれをテストする方法はありますか?
明確化:innodb_lock_wait_timeout
トランザクションがロックを解除するまで待機する秒数を設定します。私が望むのは、ロックを強制的に解除する方法です。
更新1:innodb_lock_wait_timeout
2番目のトランザクションが最初のトランザクションによってブロックされないようにするのに十分ではない理由を示す簡単な例を次に示します。
START TRANSACTION;
SELECT SLEEP(55);
COMMIT;
のデフォルト設定ではinnodb_lock_wait_timeout = 50
、このトランザクションは55秒後にエラーなしで完了します。またUPDATE
、SLEEP
行の前にを追加してからSELECT ... FOR UPDATE
、同じ行を試行する別のクライアントから2番目のトランザクションを開始すると、スリープ状態になったトランザクションではなく、2番目のトランザクションがタイムアウトになります。
私が探しているのは、このトランザクションの安らかな眠りを終わらせる方法です。
更新2:上記の例がいかに現実的であるかについてのhobodaveの懸念に応えて、代替シナリオを次に示します。DBAはライブサーバーに接続して実行します
START TRANSACTION
SELECT ... FOR UPDATE
2行目は、アプリケーションが頻繁に書き込む行をロックします。その後、DBAは中断され、トランザクションの終了を忘れて立ち去ります。行がロック解除されるまで、アプリケーションは停止します。この間違いの結果としてアプリケーションがスタックする時間を最小限にしたいと思います。
ROLLBACK
数n
秒以上かかる場合、最初のトランザクションでaを強制します。そうする方法はありますか?
MYSQL
、このシナリオを防ぐための構成がないのも不思議です。クライアントの無責任のためにサーバーがハングするのは許容できないためです。私はあなたの質問を理解するのに何の困難も見つけませんでした、それもとても関連しています。