Linuxサーバーで動かすMySQLには、こうした定期処理を自前で実装する場面があります。古いログの削除、日次の集計更新、月次のパーティション追加。これらをOSのcronから叩くにはシェルスクリプトとMySQLの認証情報の管理が必要で、意外と手間がかかります。
この記事では、MySQLに標準で用意されているイベントスケジューラー機能(
CREATE EVENT)を使って、DBサーバーの中だけで定期処理を完結させる手順を解説します。有効化の方法、実際のEVENT作成例、監視・削除まで、RHEL 9.4 / Rocky Linux 9 + MySQL 8.4(LTS)で動作確認しています。この記事のポイント
・MySQLイベントスケジューラーはcronを使わずDBの中で定期処理を自動化できる
・event_scheduler=ONをmy.cnfに設定して永続化することが前提
・CREATE EVENTでSQL文を定期実行し、SHOW EVENTSで状態を確認できる
・実行ログはperformance_schemaのevents_statements_historyで追うことができる
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
MySQLイベントスケジューラーとcronの違い
MySQLのイベントスケジューラーはMySQL本体が持つタスク実行エンジンです。CREATE EVENT文で登録したSQLやストアドプロシージャを、指定のスケジュールで自動実行します。Linux cronとの違いを整理すると以下のようになります。
・認証情報の管理: cronからmysqlコマンドを叩く場合は認証情報の取り扱いが必要。イベントスケジューラーはMySQL内部で実行するため不要
・実行ユーザー: EVENT作成者のMySQLユーザー権限で実行される(rootで作成すれば全テーブルに操作可能)
・タイムゾーン依存: MySQLの
time_zone設定に依存する。OS側のタイムゾーンとずれていると実行時刻がずれる・複雑な処理: 複数のSQLを組み合わせた処理はストアドプロシージャと組み合わせて実装する
DB内部のテーブル操作だけで完結するバッチ処理(古いレコードの削除、集計テーブルの更新など)はイベントスケジューラーが向いています。外部ファイル操作・メール送信・複数DBをまたぐ処理はcronとシェルスクリプトの方が扱いやすいです。
イベントスケジューラーを有効にする
1. 現在の状態を確認する
まず現在のイベントスケジューラーの状態を確認します。mysql> SHOW VARIABLES LIKE 'event_scheduler'; +-----------------+-------+ | Variable_name | Value | +-----------------+-------+ | event_scheduler | OFF | +-----------------+-------+
OFFの場合はイベントスケジューラーが停止しています。デフォルトはOFFです。2. 一時的に有効化する(動作確認用)
まずは動作確認のためにSET GLOBALで一時的に有効化します。mysql> SET GLOBAL event_scheduler = ON; Query OK, 0 rows affected (0.00 sec) mysql> SHOW VARIABLES LIKE 'event_scheduler'; +-----------------+-------+ | Variable_name | Value | +-----------------+-------+ | event_scheduler | ON | +-----------------+-------+
3. my.cnfで永続化する
SET GLOBALで有効にしてもMySQLを再起動するとOFFに戻ります。/etc/my.cnfの[mysqld]セクションに以下を追記してください。[mysqld] # イベントスケジューラーを常時有効化する event_scheduler = ON
sudo systemctl restart mysqld sudo systemctl status mysqld
SHOW VARIABLES LIKE 'event_scheduler'でONになっていることを確認します。
Linux Master Pro Seminar の詳細を見る >>
CREATE EVENTでイベントを作成する
イベントスケジューラーが有効になったら、CREATE EVENT文でイベントを登録します。基本構文は以下の通りです。
CREATE EVENT イベント名 ON SCHEDULE スケジュール定義 [ON COMPLETION [NOT] PRESERVE] [ENABLE | DISABLE] DO 実行するSQL文またはBEGIN...END;
1. 毎日古いレコードを削除するイベント
例として、app_logsテーブルから90日以上前のレコードを毎日深夜2時に削除するイベントを作成します。-- app_logsテーブルから90日以上前のレコードを毎日02:00に削除する CREATE EVENT evt_purge_old_logs ON SCHEDULE EVERY 1 DAY STARTS CURDATE() + INTERVAL 2 HOUR ON COMPLETION PRESERVE ENABLE DO DELETE FROM app_logs WHERE created_at < NOW() - INTERVAL 90 DAY;
・
ON SCHEDULE EVERY 1 DAY: 1日ごとに繰り返す・
STARTS CURDATE() + INTERVAL 2 HOUR: 今日の02:00から開始する・
ON COMPLETION PRESERVE: 一度実行された後もイベント定義を保持する(削除されないようにする)2. 毎月1日に集計テーブルを更新するイベント
毎月1日の午前3時に集計テーブルをリフレッシュする例です。-- 毎月1日03:00にmonthly_summaryテーブルを更新する CREATE EVENT evt_monthly_summary ON SCHEDULE EVERY 1 MONTH STARTS '2026-10-01 03:00:00' ON COMPLETION PRESERVE ENABLE DO BEGIN -- 前月分の集計をmonthly_summaryへ挿入する INSERT INTO monthly_summary (year_month, total_orders, total_amount) SELECT DATE_FORMAT(ordered_at, '%Y-%m'), COUNT(*), SUM(amount) FROM orders WHERE ordered_at >= LAST_DAY(NOW() - INTERVAL 1 MONTH) - INTERVAL DAY(LAST_DAY(NOW() - INTERVAL 1 MONTH))-1 DAY AND ordered_at < LAST_DAY(NOW() - INTERVAL 1 MONTH) + INTERVAL 1 DAY ON DUPLICATE KEY UPDATE total_orders = VALUES(total_orders), total_amount = VALUES(total_amount); END;
BEGIN...ENDブロックを使います。デリミタ問題に注意してください(mysqlコマンドラインではDELIMITER //で区切り文字を変更してから実行する必要があります)。3. 一度だけ実行するイベント(AT構文)
繰り返しではなく、特定の日時に1回だけ実行したい場合はATを使います。-- 2026-10-01 00:00:00に1回だけ実行して定義も削除するイベント CREATE EVENT evt_oneshot_migration ON SCHEDULE AT '2026-10-01 00:00:00' DO UPDATE users SET status = 'active' WHERE status = 'pending' AND created_at < '2026-01-01';
ON COMPLETION NOT PRESERVEがデフォルトのため、実行後にイベント定義は自動削除されます。イベントの確認・変更・削除
1. イベント一覧を確認する
-- 現在のデータベースのイベントを確認する SHOW EVENTS; -- または全データベースのイベントを確認する SELECT EVENT_SCHEMA, EVENT_NAME, STATUS, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, LAST_EXECUTED, NEXT_NOT_CACHED_AT FROM information_schema.EVENTS\G
EVENT_SCHEMA: appdb EVENT_NAME: evt_purge_old_logs STATUS: ENABLED EXECUTE_AT: NULL INTERVAL_VALUE: 1 INTERVAL_FIELD: DAY LAST_EXECUTED: 2026-09-21 02:00:01 NEXT_NOT_CACHED_AT: 2026-09-22 02:00:01
LAST_EXECUTEDで最後に実行された日時を確認できます。2. イベントを一時停止・再開する
-- イベントを無効化(一時停止)する ALTER EVENT evt_purge_old_logs DISABLE; -- イベントを再び有効化する ALTER EVENT evt_purge_old_logs ENABLE;
3. イベントを削除する
-- イベントを削除する DROP EVENT IF EXISTS evt_purge_old_logs;
イベントの実行ログを確認する方法
MySQLにはイベント専用の実行ログ出力機能はありませんが、performance_schemaのevents_statements_history_longテーブルで追跡できます。-- イベントによるSQL実行履歴を確認する SELECT EVENT_NAME, SQL_TEXT, TIMER_START, TIMER_END, ERRORS, ROWS_AFFECTED FROM performance_schema.events_statements_history_long WHERE CURRENT_SCHEMA = 'appdb' ORDER BY TIMER_START DESC LIMIT 10;
/var/log/mysqld.logまたは/var/log/mysql/error.log)にもイベント実行中のエラーが記録されます。イベントが失敗している疑いがある場合はエラーログを確認してください。# MySQLエラーログでイベント関連エラーを確認する sudo grep -i 'event\|scheduler' /var/log/mysqld.log | tail -20
トラブルシュートとよくある間違い
イベントが実行されない場合
イベントを作成したのに実行されない場合、まず以下の3点を確認します。・
SHOW VARIABLES LIKE 'event_scheduler'でONになっているか確認する(ONでなければ有効化する)・
SHOW EVENTSでSTATUSがENABLEDになっているか確認する・イベントのSTARTS日時が未来の日時になっていないか確認する(過去日時を指定すると最初の実行は即時)
また、イベント作成者のMySQLユーザーが対象テーブルへの権限を持っているかも確認してください。
-- イベント作成者の権限を確認する SHOW GRANTS FOR 'イベント作成ユーザー'@'localhost';
タイムゾーンと実行時刻のずれ
「深夜2時に実行したのに9時に動いた」という問題はMySQLのタイムゾーン設定とOSのタイムゾーンのずれが原因です。-- MySQLとOSのタイムゾーンを確認する mysql> SELECT @@global.time_zone, @@session.time_zone, NOW(); +--------------------+---------------------+---------------------+ | @@global.time_zone | @@session.time_zone | NOW() | +--------------------+---------------------+---------------------+ | SYSTEM | SYSTEM | 2026-09-21 14:30:00 | +--------------------+---------------------+---------------------+ # OS側のタイムゾーンを確認する timedatectl | grep 'Time zone'
@@global.time_zoneがSYSTEMの場合、MySQLはOSのタイムゾーンに従います。OSのタイムゾーンがUTCであれば、JSTの深夜2時は実際にはUTC 17:00であるため、UTC 17:00にイベントが動きます。日本のサーバーでOSのタイムゾーンがJSTに設定されていれば問題ありませんが、UTCのままにしているサーバーでは
my.cnfで明示的にタイムゾーンを設定することを推奨します。[mysqld] # MySQLのタイムゾーンを日本時間に固定する default-time-zone = '+09:00'
本記事のまとめ
MySQLイベントスケジューラーの主要な操作をまとめます。| やりたいこと | コマンド・SQL |
|---|---|
| スケジューラーの状態を確認する | SHOW VARIABLES LIKE 'event_scheduler'; |
| スケジューラーを動的に有効化する | SET GLOBAL event_scheduler = ON; |
| my.cnfで永続化する | [mysqld]セクションにevent_scheduler = ONを追記 |
| 繰り返しイベントを作成する | CREATE EVENT 名前 ON SCHEDULE EVERY 1 DAY STARTS ... DO SQL文; |
| 1回限りのイベントを作成する | CREATE EVENT 名前 ON SCHEDULE AT '日時' DO SQL文; |
| イベント一覧を確認する | SHOW EVENTS; |
| イベントを無効化・再開する | ALTER EVENT 名前 DISABLE; / ALTER EVENT 名前 ENABLE; |
| イベントを削除する | DROP EVENT IF EXISTS 名前; |
Linux Master Pro Seminar の詳細を見る >>
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 前のページへ:MySQLの一般クエリログ(general_log)を有効化して全SQLを記録する方法|設定手順と運用上の注意点
- この記事の属するカテゴリ:データーベース管理へ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます