0

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

4

1 に答える 1