概要
ストアド プロシージャを呼び出すイベントがある場合、一度に実行されるプロシージャのインスタンスが 1 つだけであることを確認するためのベスト プラクティスは何ですか? 具体的には、イベントがティックオーバーするのにかかる時間よりも、プロシージャの実行に時間がかかる場合があります。
例
次の捏造された例を考えてみましょう。イベントのティックオーバーに1秒かかり、プロシージャの実行に5秒かかります。
手順:
DELIMITER ;;
CREATE PROCEDURE `P_wait`()
BEGIN
SELECT SLEEP(5);
END;;
DELIMITER ;
イベント:
DROP EVENT IF EXISTS `E_wait`;
DELIMITER ;;
CREATE EVENT `E_wait`
ON SCHEDULE
EVERY 1 SECOND
DO
BEGIN
CALL `P_wait`(); //proc_call
END;;
DELIMITER ;
ご想像のとおり、イベントの実行中は、 に の 5 つのインスタンスが表示SLEEP()
されPROCESSLIST
ます。
mysql> SHOW PROCESSLIST;
+-------+------+-----------+-------+---------+------+-------------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+-------+------+-----------+-------+---------+------+-------------+------------------+
| 27045 | root | localhost | temp | Query | 0 | NULL | SHOW PROCESSLIST |
| 27069 | root | localhost | temp | Connect | 4 | User sleep | SELECT SLEEP(5) |
| 27070 | root | localhost | temp | Connect | 3 | User sleep | SELECT SLEEP(5) |
| 27072 | root | localhost | temp | Connect | 2 | User sleep | SELECT SLEEP(5) |
| 27073 | root | localhost | temp | Connect | 1 | User sleep | SELECT SLEEP(5) |
| 27074 | root | localhost | temp | Connect | 0 | User sleep | SELECT SLEEP(5) |
+-------+------+-----------+-------+---------+------+-------------+------------------+
この例ではそうではありませんが、プロシージャがブロックされていた場合 ( SELECT ... FOR UPDATE
Statement を含むトランザクションが含まれている場合など)、これがすぐに問題に発展することがわかります。
質問
E_wait
が 1 秒ごとに刻み込まれ、 のインスタンスP_wait
がまだ実行されている場合に再度呼び出されないようにする最善の方法は何ですか? P_wait
一度に実行するインスタンスは最大でも 1 つだけです。ここでのベストプラクティスは何ですか?
基本的に/*PROCEDURE_NOT_RUNNING*/
、イベントを次のように変更した場合、代わりに何を配置する必要があります:
...
BEGIN
IF /*PROCEDURE_NOT_RUNNING*/ THEN
CALL wait_test(); //proc_call
END IF;
END;;
...
- 手順内からイベント
E_wait
を変更する (最初に無効にP_wait
し、最後に再度有効にする) ことはできません。これは、イベントが無効になっている間にサーバーが再起動すると、イベントがまったく実行されなくなる可能性があるためです。 - テーブルに値を保存して、それを使用してプロシージャがまだ実行されているかどうかを確認することもできますが、サーバーが正確に間違った時間に実行を停止すると、ロックアップする可能性があるという同じ問題が発生するようです。
- この議論の全体的なポイントは、手順の実行に任意に長い時間がかかる可能性があるため、イベントスケジュールを 5 秒に変更するだけでは受け入れられないということです:P
望ましい結果
上記のイベントを実行し、最大で 1 つのSELECT SLEEP(5)
inのインスタンスのみを表示するにはSHOW PROCESSLIST
。