Запланированные события (Events)
В реальных приложениях часто возникает необходимость выполнять определённые действия автоматически и по расписанию: очищать старые записи, обновлять статистику, формировать отчёты. Для таких задач SQL предоставляет механизм запланированных событий.
Событие — это задача, которую база данных запускает сама по расписанию. Вы настраиваете — оно работает автоматически.
События в MySQL похожи на планировщик задач в операционной системе: вы создаёте задачу один раз, а база данных выполняет её автоматически по расписанию.
В PostgreSQL для автоматического выполнения задач используется расширение pg_cron. Это расширение позволяет планировать SQL-команды с использованием синтаксиса cron (как в Unix-системах).
Когда он пригодится
Запланированные события помогают автоматизировать следующие задачи:
- Очистка данных: удаление устаревших записей логов или временных данных
- Обновление статистики: пересчёт агрегированных данных для аналитики
- Генерация отчётов: автоматическое формирование периодических отчётов
- Резервное копирование: создание копий важных данных
Как включить планировщик
Прежде чем создавать события, необходимо убедиться, что планировщик событий включён:
MySQL 8.1SHOW VARIABLES LIKE 'event_scheduler';
Если планировщик выключен, включите его:
MySQL 8.1SET GLOBAL event_scheduler = ON;
Для использования запланированных задач в PostgreSQL нужно установить расширение pg_cron:
MySQL 8.1CREATE EXTENSION IF NOT EXISTS pg_cron;
Важно: Расширение pg_cron может требовать прав суперпользователя и дополнительной настройки PostgreSQL. В облачных сервисах (AWS RDS, Azure) оно может быть уже предустановлено.
Создание одноразового события
Начнём с самого простого — события, которое выполнится один раз в определённое время:
MySQL 8.1CREATE EVENT cleanup_old_logs ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 DAY DO DELETE FROM logs WHERE created_at < NOW() - INTERVAL 30 DAY;
Это событие удалит записи логов старше 30 дней через 24 часа после создания события.
Разберём синтаксис:
- CREATE EVENT cleanup_old_logs — создаём событие с именем cleanup_old_logs
- ON SCHEDULE AT — указываем, когда событие должно выполниться
- CURRENT_TIMESTAMP + INTERVAL 1 DAY — время выполнения (через 1 день)
- DO — код, который нужно выполнить (любой SQL-оператор)
MySQL 8.1SELECT cron.schedule( 'cleanup_old_logs', '0 3 * * *', 'DELETE FROM logs WHERE created_at < NOW() - INTERVAL ''30 days''' );
Это событие будет выполняться каждый день в 3:00 утра и удалять записи логов старше 30 дней.
Разберём синтаксис:
- cron.schedule() — функция для создания запланированной задачи
- 'cleanup_old_logs' — имя задачи
- '0 3 * * *' — расписание в формате cron (минута час день месяц день_недели)
- Последний параметр — SQL-команда для выполнения
Формат cron расписания:

Создание повторяющегося события
Чаще всего события нужно запускать периодически — каждый день, час или минуту:
MySQL 8.1CREATE EVENT update_statistics ON SCHEDULE EVERY 1 HOUR DO BEGIN UPDATE product_stats SET total_sales = (SELECT SUM(amount) FROM orders WHERE product_id = product_stats.product_id), last_updated = NOW(); END;
Это событие будет обновлять статистику продаж каждый час.
Разберём синтаксис:
- ON SCHEDULE EVERY 1 HOUR — выполнять каждый час
- BEGIN ... END — блок из нескольких SQL-операторов
Варианты интервалов:
- EVERY 1 MINUTE — каждую минуту
- EVERY 1 HOUR — каждый час
- EVERY 1 DAY — каждый день
- EVERY 1 WEEK — каждую неделю
- EVERY 1 MONTH — каждый месяц
- EVERY 30 SECOND — каждые 30 секунд
MySQL 8.1SELECT cron.schedule( 'update_statistics_hourly', '0 * * * *', $$ UPDATE product_stats SET total_sales = (SELECT SUM(amount) FROM orders WHERE product_id = product_stats.product_id), last_updated = NOW() $$ );
Это событие будет обновлять статистику продаж каждый час (в начале каждого часа).
Примеры расписаний:
- '*/5 * * * *' — каждые 5 минут
- '0 * * * *' — каждый час (в начале часа)
- '0 0 * * *' — каждый день в полночь
- '0 0 * * 0' — каждое воскресенье в полночь
- '0 9 1 * *' — первого числа каждого месяца в 9:00
Событие с ограниченным сроком действия
Иногда нужно, чтобы событие работало только в определённый период:
MySQL 8.1CREATE EVENT seasonal_discount ON SCHEDULE EVERY 1 DAY STARTS '2025-12-01 00:00:00' ENDS '2025-12-31 23:59:59' DO UPDATE products SET price = price * 0.9 WHERE category = 'seasonal';
Это событие будет применять скидку 10% на сезонные товары каждый день в течение декабря 2025 года.
Новые элементы:
- STARTS — начало периода действия события
- ENDS — конец периода действия события
После указанной даты событие автоматически прекратит выполняться.
В pg_cron нет встроенной поддержки автоматического завершения задач, но можно включить проверку даты в саму команду:
MySQL 8.1SELECT cron.schedule( 'seasonal_discount', '0 0 * * *', $$ UPDATE products SET price = price * 0.9 WHERE category = 'seasonal' AND CURRENT_DATE BETWEEN '2025-12-01' AND '2025-12-31' $$ );
Альтернативно, можно создать задачу на удаление события в конце периода:
MySQL 8.1SELECT cron.schedule( 'remove_seasonal_discount', '0 0 1 1 *', -- 1 января в полночь $$SELECT cron.unschedule('seasonal_discount')$$ );
Просмотр существующих событий
Чтобы увидеть все созданные события:
MySQL 8.1SHOW EVENTS;
Для просмотра событий в конкретной базе данных:
MySQL 8.1SHOW EVENTS FROM your_database_name;
Чтобы увидеть все запланированные задачи:
MySQL 8.1SELECT * FROM cron.job;
Это вернёт таблицу со всеми задачами, включая их расписание и команды.
Для просмотра истории выполнения задач:
MySQL 8.1SELECT * FROM cron.job_run_details ORDER BY start_time DESC LIMIT 10;
Управление событиями
Временное отключение события:
MySQL 8.1ALTER EVENT cleanup_old_logs DISABLE;
Включение события:
MySQL 8.1ALTER EVENT cleanup_old_logs ENABLE;
Изменение расписания события:
MySQL 8.1ALTER EVENT cleanup_old_logs ON SCHEDULE EVERY 2 HOUR;
Удаление события:
MySQL 8.1DROP EVENT IF EXISTS cleanup_old_logs;
Удаление запланированной задачи:
MySQL 8.1SELECT cron.unschedule('cleanup_old_logs');
Или по ID задачи:
MySQL 8.1SELECT cron.unschedule(42); -- где 42 - это jobid из таблицы cron.job
Изменение задачи:
В pg_cron нельзя изменить существующую задачу напрямую. Нужно удалить старую и создать новую:
MySQL 8.1-- Удаляем старую SELECT cron.unschedule('cleanup_old_logs'); -- Создаём новую с обновлённым расписанием SELECT cron.schedule( 'cleanup_old_logs', '0 */2 * * *', -- Каждые 2 часа 'DELETE FROM logs WHERE created_at < NOW() - INTERVAL ''30 days''' );
Важные моменты при работе с событиями
- 
Права доступа: Для создания событий нужна привилегия EVENT. 
- 
Временная зона: События выполняются по временной зоне сервера базы данных. 
- 
Производительность: Избегайте создания событий со слишком коротким интервалом (каждую минуту), это может повлиять на производительность. 
- 
Права доступа: Для использования pg_cron обычно требуются права суперпользователя или специальная настройка. 
- 
Временная зона: Задачи pg_cron выполняются по временной зоне PostgreSQL (можно проверить через SHOW timezone;). 
- 
Производительность: Pg_cron проверяет расписание каждую секунду, поэтому минимальная точность — 1 минута. 
- 
Логирование: Все выполнения задач сохраняются в таблице cron.job_run_details, что полезно для отладки. 
Самопроверка
Какой минимальный интервал можно использовать для повторяющихся событий?
Запланированные события — это мощный инструмент для автоматизации рутинных задач в базе данных. Они помогают поддерживать чистоту данных, обновлять статистику и выполнять регламентные операции без участия разработчиков! 🚀
