MySQL で、少なくとも 30 秒ごとに非常に頻繁に実行したいイベントがあります。
最近更新されたレコードを含むキュー テーブルからのデータを処理しています。ときどき大量の更新を受け取ることがあります。これが発生すると、イベントの実行に通常の 2 ~ 3 秒よりも時間がかかる場合があります。次の予定の時刻になっても実行中であれば、次のイベントは実行を飛ばしたい。
これを行うための最良の方法は、プロセスの開始時に特定のキーを 1 に設定し、プロセスが完了したら 0 に戻す「状態」テーブルを作成することです。次に、イベントを変更して現在のステータスを確認します。
それよりももっと素敵なことをしたいです。完全に欠けている機能はありますか?
グローバル変数を調べましたが、ドキュメントに基づいて、これらはシステム変数に対してのみ許可されているようです。
現在のコード例
これが私が現在テストしているサンプルコードです。
acca_sync: BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN
GET DIAGNOSTICS CONDITION 1 @sqlstate = RETURNED_SQLSTATE,
@errno = MYSQL_ERRNO, @text = MESSAGE_TEXT;
SET @full_error = CONCAT("ERROR ", @errno, " (", @sqlstate, "): ", @text);
call pa.log(concat("acca-acc_sync"," - Error - ", ifnull(@full_error, "no error message")));
UPDATE `acca`.`processing_state`
SET `value` = 0
WHERE `key` = 'acca_sync';
END;
call pa.log(CONCAT("Started acca_sync @ ", NOW()));
SELECT `value`
into @is_locked
from `acca`.`processing_state`
where `key` = 'acca_sync';
IF @is_locked = 0 THEN
UPDATE `acca`.`processing_state`
SET `value` = 1
WHERE `key` = 'acca_sync';
ELSE
CALL pa.log(CONCAT("acca_sync deferred due to active sync. @ ", NOW()));
LEAVE acca_sync;
END IF;
call acca.event_sync();
call pa.log(CONCAT("Completed acca_sync @ ", NOW()));
UPDATE `acca`.`processing_state`
SET `value` = 0
WHERE `key` = 'acca_sync';
END
テーブルのロック
コメントに基づいて、テーブルロックを使用していない理由を説明したいと思います。テーブルロックに関する私の経験は限られているので、以下が正しく、理にかなっていることを願っています.
ソース データ テーブル
キュー テーブルの更新を通知するトリガーがあります。これらは、データを読み取って処理するソース データ テーブルです。
私の理解では、READ
これらのテーブルをロックしても、読み取りだけの他のイベントはロックされません。ロックを使用する場合はWRITE
、現在アクセスしていない行への更新をブロックします。
ターゲット データ テーブル
さまざまなイベントでデータを処理する複数のデータ ソースがあります。これらがターゲット テーブルで修正する行。2 つの異なるイベントが同時に実行され、同じテーブルへの書き込みが行われる可能性があるため、ターゲット テーブルを人為的にブロックしたくありません。
その他のテーブル
ロックの設定とその存在の確認のみを目的とした偽のテーブルを作成できます。これはばかげているように思えます。代わりに、毎回照会するlock_key
および列を持つ単一のテーブル ロックを作成したいと思います。is_locked