MySQLのイベントスケジューラーを使ってデータ定期削除・集計を自動化する手順|CREATE EVENTの実践

宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
HOMELinux技術 リナックスマスター.JP(Linuxマスター.JP)Linuxtipsデーターベース管理 > MySQLのイベントスケジューラーを使ってデータ定期削除・集計を自動化する手順|CREATE EVENTの実践
「MySQLのデータが無限に溜まっていく。cronでshellを書くのも手間だし、DBの中で完結できないか」

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で追うことができる


「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

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

設定を反映するにはMySQLの再起動が必要です。

sudo systemctl restart mysqld sudo systemctl status mysqld

再起動後、SHOW VARIABLES LIKE 'event_scheduler'でONになっていることを確認します。
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、MySQLの設定・チューニング・運用を含むLinuxサーバーの実践スキルを現役エンジニアが指導します。
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;

複数のSQLを実行する場合は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

実際のサーバーでの出力例(db-server01)は以下のようになります。

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_schemaevents_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;

また、MySQLのエラーログ(/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_zoneSYSTEMの場合、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 名前;
cronなしでMySQLのデータ管理を完結できるイベントスケジューラーは、シェルスクリプトの管理コストを下げながらDBの自動メンテナンスを実現できます。まずは古いレコードの定期削除から試してみてください。
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、MySQLの設定・チューニング・運用を含むLinuxサーバーの実践スキルを現役エンジニアが指導します。
Linux Master Pro Seminar の詳細を見る >>

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録
宮崎 智広

この記事を書いた人

宮崎 智広(みやざき ともひろ)

株式会社イーネットマーキュリー代表。現役のLinuxサーバー管理者として20年以上の実務経験を持ち、これまでに累計3,100名以上のエンジニアを指導してきたLinux教育のプロフェッショナル。「現場で本当に使える技術」を体系的に伝えることをモットーに、実践型のLinuxセミナーの開催や無料マニュアルの配布を通じてLinux人材の育成に取り組んでいる。

趣味は、キャンプにカメラ、トラウト釣り。好きな食べ物は、ラーメンにお酒。休肝日が作れない、酒量を減らせないのが悩み。最近、ドラマ「フライトエンジェル」を観て涙腺が崩壊しました。