MySQL - イベントスケジューラ

提供: MochiuWiki : SUSE, EC, PCB

2026年2月15日 (日) 18:30時点におけるWiki (トーク | 投稿記録)による版 (ページの作成:「== 概要 == MySQLのイベントスケジューラは、データベース内でスケジュール済みタスクを自動実行する機能である。<br> これは、cronのようなスケジューリング機能をMySQL内で提供するものであり、定期的なメンテナンスやデータ整理、集計処理を自動化できる。<br> <br> イベントスケジューラは、MySQL 5.1以降で利用可能である。<br> <br> イベントには、1度…」)
(差分) ← 古い版 | 最新版 (差分) | 新しい版 → (差分)

概要

MySQLのイベントスケジューラは、データベース内でスケジュール済みタスクを自動実行する機能である。
これは、cronのようなスケジューリング機能をMySQL内で提供するものであり、定期的なメンテナンスやデータ整理、集計処理を自動化できる。

イベントスケジューラは、MySQL 5.1以降で利用可能である。

イベントには、1度限り実行される ATイベント と、繰り返し実行される EVERYイベント の2種類がある。

  • ATイベント
    指定された日時に1度だけ実行される。
  • EVERYイベント
    指定された間隔で繰り返し実行される。


イベントスケジューラは、event_scheduler システム変数によって制御される。
この変数は、ON、OFF、DISABLEDの3つの状態を持ち、ランタイムで切り替えが可能である。(DISABLEDを除く)

イベントは、CREATE EVENT 文で作成し、ALTER EVENT 文で変更し、DROP EVENT 文で削除する。
イベントの情報は、INFORMATION_SCHEMA.EVENTS テーブルから確認できる。

イベントスケジューラの主な用途には、古いログの定期削除、集計テーブルの更新、テーブル最適化、バックアップ処理等がある。
SQL内で完結するため、外部スクリプトが不要であり、OS非依存で移植性が高いという利点がある。


イベントスケジューラの有効化

event_scheduler変数

イベントスケジューラの動作は、event_scheduler システム変数で制御される。

この変数には、以下の3つの状態がある。
br>

イベントスケジューラの状態
状態 説明
ON (または 1) イベントスケジューラが有効であり、イベントが実行可能な状態である。
スケジューラスレッドが起動し、SHOW PROCESSLIST に表示される。
OFF (または 0) イベントスケジューラが無効であり、イベントは実行されない。
スレッドは停止しているが、ランタイムでONに切り替え可能である。
DISABLED イベントスケジューラが完全に無効化されている。
サーバ起動時のみ設定可能であり、ランタイムでは変更できない。


イベントスケジューラをランタイムで有効化する構文を以下に示す。

 SET GLOBAL event_scheduler = ON;


サーバ起動時にイベントスケジューラを有効化するには、my.cnfファイル に以下に示す設定を追加する。

 [mysqld]
 event_scheduler = ON


状態の確認

イベントスケジューラの現在の状態を確認する方法を以下に示す。

 SHOW VARIABLES LIKE 'event_scheduler';


または、グローバル変数を直接参照する。

 SELECT @@GLOBAL.event_scheduler;


イベントスケジューラスレッドが起動しているかどうかを確認する。

 SHOW PROCESSLIST;


event_scheduler が ON の場合、User が event_scheduler、Command が Daemon のプロセスが表示される。


イベントの作成

基本構文

イベントを作成するには、CREATE EVENT 文を使用する。

 CREATE
    [DEFINER = <ユーザ名>]
    EVENT [IF NOT EXISTS] <イベント名>
    ON SCHEDULE <スケジュール>
    [ON COMPLETION [NOT] PRESERVE]
    [ENABLE | DISABLE | DISABLE ON SLAVE]
    [COMMENT 'string']
    DO <イベント本体>;


下表に、主要な構文要素を示す。

主要な構文要素
構文要素 説明
DEFINER イベントを実行するユーザを指定する。
省略時は、現在のユーザが設定される。
IF NOT EXISTS 同名のイベントが存在する場合、エラーにならず警告のみが出力される。
ON SCHEDULE イベントの実行スケジュールを指定する。
ON COMPLETION イベント実行完了後の動作を指定する。
ENABLE / DISABLE イベントの有効・無効を指定する。
COMMENT イベントのコメントを指定する。
DO 実行するSQL文 または ストアドプロシージャを指定する。


スケジュール指定

イベントのスケジュールは、ON SCHEDULE 句で指定する。

 schedule: {
    AT <タイムスタンプ> [+ INTERVAL <間隔>] ...
  | EVERY <間隔>
    [STARTS <タイムスタンプ> [+ INTERVAL <間隔>] ...]
    [ENDS <タイムスタンプ> [+ INTERVAL <間隔>] ...]
 }
 
 interval:
    <数値> {YEAR | QUARTER | MONTH | DAY | HOUR | MINUTE |
              WEEK | SECOND | YEAR_MONTH | DAY_HOUR | DAY_MINUTE |
              DAY_SECOND | HOUR_MINUTE | HOUR_SECOND | MINUTE_SECOND}


AT構文は、1度限りのイベントを作成する。

 CREATE EVENT cleanup_event
    ON SCHEDULE AT '2026-03-01 03:00:00'
    DO DELETE FROM logs WHERE created_date < NOW() - INTERVAL 30 DAY;


現在時刻からの相対時刻で指定することもできる。

 CREATE EVENT temp_event
    ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR
    DO INSERT INTO status_log (message) VALUES ('Hourly check');


EVERY構文は、繰り返しイベントを作成する。

 CREATE EVENT daily_cleanup
    ON SCHEDULE EVERY 1 DAY
    DO DELETE FROM logs WHERE created_date < NOW() - INTERVAL 30 DAY;


STARTSENDS を使用して、開始日時と終了日時を指定できる。

 CREATE EVENT monthly_report
    ON SCHEDULE EVERY 1 MONTH
    STARTS '2026-01-01 00:00:00'
    ENDS '2026-12-31 23:59:59'
    DO CALL generate_monthly_report();


様々な間隔の指定例を以下に示す。

 -- 毎時間実行
 ON SCHEDULE EVERY 1 HOUR
 
 -- 15分ごとに実行
 ON SCHEDULE EVERY 15 MINUTE
 
 -- 毎週月曜日 (1週間ごと) に実行
 ON SCHEDULE EVERY 1 WEEK
    STARTS '2026-02-17 00:00:00'
 
 -- 3時間ごとに実行
 ON SCHEDULE EVERY 3 HOUR
 
 -- 30秒ごとに実行
 ON SCHEDULE EVERY 30 SECOND


ON COMPLETION

ON COMPLETION 句は、イベント実行完了後の動作を制御する。

ON COMPLETIONの動作
オプション 説明
PRESERVE イベント実行完了後も、イベント定義を保持する。
1度限りイベントでも、実行後に削除されない。
NOT PRESERVE イベント実行完了後、イベント定義を自動削除する。(デフォルト)
1度限りイベントは、実行後に自動的に削除される。


1度限りイベントを実行後も保持する例を以下に示す。

 CREATE EVENT one_time_event
    ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 DAY
    ON COMPLETION PRESERVE
    DO INSERT INTO maintenance_log (message) VALUES ('Scheduled maintenance');


繰り返しイベントは、ENDS で指定された終了日時を過ぎると完了とみなされる。
NOT PRESERVE を指定すると、終了日時後にイベント定義が削除される。

イベントの状態

イベントの有効・無効状態を指定できる。

イベントの有効・無効オプション
オプション 説明
ENABLE イベントを有効化する。(デフォルト)
DISABLE イベントを無効化する。
イベント定義は保持されるが、実行されない。
DISABLE ON SLAVE レプリケーション環境でレプリカ側では無効化する。
マスタ側でのみ実行される。


無効状態でイベントを作成する例を以下に示す。

 CREATE EVENT maintenance_event
    ON SCHEDULE EVERY 1 DAY
    DISABLE
    COMMENT 'メンテナンス用イベント (手動有効化が必要)'
    DO CALL maintenance_procedure();



イベントの実行内容

単一SQL文

DO 句には、単一のSQL文を記述できる。

 CREATE EVENT delete_old_logs
    ON SCHEDULE EVERY 1 DAY
    DO DELETE FROM logs WHERE date < NOW() - INTERVAL 30 DAY;


INSERT文 や UPDATE文も使用できる。

 CREATE EVENT update_statistics
    ON SCHEDULE EVERY 1 HOUR
    DO UPDATE stats SET last_update = CURRENT_TIMESTAMP;


複数SQL文

複数のSQL文を実行する場合は、BEGIN ... END ブロックを使用する。
デリミタを変更して、ブロック内のセミコロンと区別する必要がある。

 DELIMITER |
 
 CREATE EVENT cleanup_and_optimize
    ON SCHEDULE EVERY 1 DAY STARTS '2026-01-01 03:00:00'
    DO BEGIN
       DELETE FROM logs WHERE created_date < NOW() - INTERVAL 30 DAY;
       OPTIMIZE TABLE logs;
    END |
 
 DELIMITER ;


変数やループを使用した複雑な処理も記述できる。

以下の例では、10回に分けて1000行ずつ削除し、各削除の間に1秒の待機時間を設けている。
これにより、データベースへの負荷を分散できる。

 DELIMITER |
 
 CREATE EVENT batch_delete
    ON SCHEDULE EVERY 1 DAY
    DO BEGIN
       DECLARE i INT DEFAULT 0;
       WHILE i < 10 DO
          DELETE FROM logs WHERE created_date < NOW() - INTERVAL 90 DAY LIMIT 1000;
          SET i = i + 1;
          DO SLEEP(1);
       END WHILE;
    END |
 
 DELIMITER ;


ストアドプロシージャの呼び出し

DO 句でストアドプロシージャを呼び出すこともできる。

 CREATE EVENT daily_maintenance
    ON SCHEDULE EVERY 1 DAY STARTS '2026-01-01 02:00:00'
    DO CALL cleanup_procedure();


パラメータを渡すこともできる。

 CREATE EVENT monthly_archive
    ON SCHEDULE EVERY 1 MONTH
    DO CALL archive_old_data(90);



イベントの変更

既存のイベントを変更するには、ALTER EVENT 文を使用する。

 ALTER [DEFINER = <ユーザ名>] EVENT <イベント名>
    [ON SCHEDULE <スケジュール>]
    [ON COMPLETION [NOT] PRESERVE]
    [RENAME TO <新しいイベント名>]
    [ENABLE | DISABLE | DISABLE ON SLAVE]
    [COMMENT 'string']
    [DO <イベント本体>]


  • スケジュールを変更する例
     ALTER EVENT cleanup_event
        ON SCHEDULE EVERY 2 DAY;
    

  • イベントを無効化する例
     ALTER EVENT maintenance_event DISABLE;
    

  • イベントを有効化する例
     ALTER EVENT maintenance_event ENABLE;
    

  • イベント名を変更する例
     ALTER EVENT old_event_name
        RENAME TO new_event_name;
    

  • 実行内容を変更する例
     ALTER EVENT cleanup_event
        DO DELETE FROM logs WHERE created_date < NOW() - INTERVAL 60 DAY;
    

  • 複数の項目を同時に変更することもできる。
     ALTER EVENT maintenance_event
        ON SCHEDULE EVERY 1 WEEK
        ON COMPLETION PRESERVE
        COMMENT '毎週実行されるメンテナンスイベント';
    



イベントの削除

イベントを削除するには、DROP EVENT 文を使用する。

 DROP EVENT [IF EXISTS] <イベント名>;


イベントを削除する例を以下に示す。

 DROP EVENT cleanup_event;


IF EXISTS 句を使用すると、イベントが存在しない場合でもエラーにならず、警告のみが出力される。

 DROP EVENT IF EXISTS temp_event;



イベントの確認

イベント一覧を確認するには、SHOW EVENTS 文を使用する。

 SHOW EVENTS;


  • 特定のデータベースのイベントを確認する。
     SHOW EVENTS FROM <データベース名>;
    

  • パターンマッチングでイベントを検索する。
     SHOW EVENTS LIKE 'cleanup%';
    

  • 特定のイベントの定義を確認するには、SHOW CREATE EVENT 文を使用する。
     SHOW CREATE EVENT <イベント名>;
    

  • イベントの詳細情報は、INFORMATION_SCHEMA.EVENTS テーブルから取得できる。
     SELECT EVENT_SCHEMA, EVENT_NAME, EVENT_TYPE, EXECUTE_AT,
            INTERVAL_VALUE, INTERVAL_FIELD, STARTS, ENDS,
            STATUS, ON_COMPLETION, LAST_EXECUTED
     FROM INFORMATION_SCHEMA.EVENTS
     WHERE EVENT_NAME = 'cleanup_event';
    


INFORMATION_SCHEMA.EVENTS の主要カラム
カラム名 説明
EVENT_SCHEMA イベントが属するデータベース名
EVENT_NAME イベント名
DEFINER イベントの定義者
EVENT_TYPE ONE TIME または RECURRING
EXECUTE_AT 一度限りイベントの実行日時
INTERVAL_VALUE 繰り返しイベントの間隔値
INTERVAL_FIELD 繰り返しイベントの間隔単位 (HOUR、DAY等)
STARTS 繰り返しイベントの開始日時
ENDS 繰り返しイベントの終了日時
STATUS ENABLED、DISABLED、SLAVESIDE_DISABLED
ON_COMPLETION PRESERVE または NOT PRESERVE
LAST_EXECUTED 最後に実行された日時


全てのイベントの実行状態を確認する。

 SELECT EVENT_NAME, STATUS, LAST_EXECUTED
 FROM INFORMATION_SCHEMA.EVENTS
 WHERE EVENT_SCHEMA = DATABASE();



サンプルクエリ

古いデータの削除

  • 30日以上前のログデータを毎日削除するイベント
     CREATE EVENT cleanup_old_logs
        ON SCHEDULE EVERY 1 DAY STARTS '2026-01-01 02:00:00'
        DO DELETE FROM logs WHERE created_date < NOW() - INTERVAL 30 DAY;
    

  • 90日以上前のデータをバッチで削除し、負荷を分散する例
     DELIMITER |
     
     CREATE EVENT batch_cleanup
        ON SCHEDULE EVERY 1 DAY STARTS '2026-01-01 03:00:00'
        DO BEGIN
           DECLARE i INT DEFAULT 0;
           WHILE i < 10 DO
              DELETE FROM transaction_logs
              WHERE created_date < NOW() - INTERVAL 90 DAY
              LIMIT 1000;
              SET i = i + 1;
              DO SLEEP(1);
           END WHILE;
        END |
     
     DELIMITER ;
    


集計テーブルの更新

  • 1時間ごとにセンサデータを集計して、統計テーブルに挿入する例
     DELIMITER |
     
     CREATE EVENT update_hourly_stats
        ON SCHEDULE EVERY 1 HOUR
        DO BEGIN
           INSERT INTO hourly_stats (stat_time, count, avg_value, max_value)
           SELECT CURRENT_TIMESTAMP, COUNT(*), AVG(value), MAX(value)
           FROM sensor_readings
           WHERE timestamp > CURRENT_TIMESTAMP - INTERVAL 1 HOUR;
        END |
     
     DELIMITER ;
    

  • 毎日の売上集計を作成する例
     DELIMITER |
     
     CREATE EVENT daily_sales_summary
        ON SCHEDULE EVERY 1 DAY STARTS '2026-01-01 23:00:00'
        DO BEGIN
           INSERT INTO daily_sales (sale_date, total_amount, order_count)
           SELECT CURDATE(), SUM(amount), COUNT(*)
           FROM orders
           WHERE DATE(order_date) = CURDATE();
        END |
     
     DELIMITER ;
    


定期メンテナンス

  • 毎週テーブルを最適化し、統計情報を更新するイベントを作成する。
     DELIMITER |
     
     CREATE EVENT weekly_maintenance
        ON SCHEDULE EVERY 1 WEEK STARTS '2026-01-05 03:00:00'
        DO BEGIN
           OPTIMIZE TABLE users;
           OPTIMIZE TABLE transactions;
           OPTIMIZE TABLE logs;
           ANALYZE TABLE users;
           ANALYZE TABLE transactions;
           ANALYZE TABLE logs;
        END |
     
     DELIMITER ;
    

  • 毎月1日にレポートを生成するイベントを作成する。
     CREATE EVENT monthly_report_generation
        ON SCHEDULE EVERY 1 MONTH STARTS '2026-03-01 01:00:00'
        DO CALL generate_monthly_report();
    



CRONとの比較

下表に、イベントスケジューラとCRONの比較を示す。

イベントスケジューラ と CRONの比較
項目 イベントスケジューラ cron
実行環境 MySQL内 OS (UNIX系システム)
設定場所 データベース内 crontabファイル
実行内容 SQL文、ストアドプロシージャ シェルスクリプト、コマンド、プログラム
OS依存性 非依存 (移植性が高い) 依存 (UNIX系のみ)
権限管理 DEFINER で一元管理 ユーザ権限、ファイルシステム権限
ログ確認 INFORMATION_SCHEMA.EVENTS syslog、cronログ
データベース停止時 実行されない 実行可能 (データベース接続が必要)
複雑な処理 SQLの範囲内 任意のプログラム実行可能
スケジューリング精度 秒単位 分単位 (標準)
エラーハンドリング SQLエラーハンドリング シェルスクリプトのエラー処理


イベントスケジューラ と CRONのメリット
方式 メリット
イベントスケジューラ SQL内で完結し、外部スクリプトが不要である
OS非依存で移植性が高い。
DEFINER権限で一元管理できる。
INFORMATION_SCHEMA.EVENTS で実行情報を確認できる。
データベースと一体化しており、バックアップ時にイベント定義も含められる。
cron シェルスクリプトや外部プログラムを実行できる。
POSIX標準で多くのシステムで利用可能である。
データベース停止時も動作可能である。
より柔軟なスケジューリングが可能である。
システムレベルのタスクを実行できる。


用途に応じて、イベントスケジューラとCRONを使い分けることが推奨される。
データベース内部の定期処理にはイベントスケジューラを使用し、外部プログラムの実行やシステムレベルのタスクにはCRONを使用するとよい。


イベントスケジューラの制限事項

イベントスケジューラには、以下に示すような制限事項がある。

イベントスケジューラの制限事項
制限事項 説明
LOCK TABLES / UNLOCK TABLES は使用不可 イベント内でテーブルロックを明示的に取得・解放することはできない。
ALTER VIEW は使用不可 イベント内でビューの定義を変更することはできない。
LOAD DATA / LOAD XML は使用不可 イベント内で外部ファイルからデータをロードすることはできない。
イベント内からのイベント操作は不可 イベント内で CREATE EVENTALTER EVENTDROP EVENT を実行することはできない。
イベント名の大文字小文字は区別されない event_name と EVENT_NAME は同一のイベントとして扱われる。
複数実行保護メカニズムがない 同じイベントが前回の実行完了前に再度トリガーされる可能性がある。
GET_LOCK() 関数で排他制御を実装する必要がある。
年2038以上の日付はサポートされない 32ビット UNIXエポックの制限により、2038年1月19日以降の日付を正確に扱えない場合がある。


複数実行を防ぐための排他制御の例を以下に示す。

以下の例では、GET_LOCK() 関数でロックを取得して、ロック取得に成功した場合のみ処理を実行する。
GET_LOCK('my_event_lock', 0) の第2パラメータ 0は、タイムアウトを0秒に設定しており、即座にロック取得の成否を返す。

 DELIMITER |
 
 CREATE EVENT protected_event
    ON SCHEDULE EVERY 5 MINUTE
    DO BEGIN
       DECLARE lock_acquired INT;
       SET lock_acquired = GET_LOCK('my_event_lock', 0);
 
       IF lock_acquired = 1 THEN
          -- 実際の処理
          DELETE FROM logs WHERE created_date < NOW() - INTERVAL 30 DAY;
 
          DO RELEASE_LOCK('my_event_lock');
       END IF;
    END |
 
 DELIMITER ;



関連ページ