Статьи

Работа с MySQL Events

События MySQL были добавлены в MySQL 5.1.6 и предлагают альтернативу запланированным задачам и заданиям cron. События можно использовать для создания резервных копий, удаления устаревших записей, агрегирования данных для отчетов и т. Д. В отличие от стандартных триггеров, которые выполняются при определенных условиях, событие — это объект, который запускается с течением времени и иногда называется временным триггером . Вы можете запланировать запуск событий один раз или с периодическими интервалами, когда вы знаете, что трафик вашего сервера будет низким.

В этой статье я объясню, что вам нужно знать, чтобы начать использовать события: запуск планировщика событий, добавление событий для запуска один или несколько раз, просмотр существующих событий и изменение событий. Я также поделюсь с вами тем, как вы можете использовать события MySQL, используя запланированные посты в блоге, в качестве практического примера.

Запуск планировщика событий

Планировщик событий MySQL — это процесс, который работает в фоновом режиме и постоянно ищет события для выполнения. Прежде чем вы сможете создать или запланировать событие, вам необходимо сначала включить планировщик, выполнив следующую команду:

  mysql> SET GLOBAL event_scheduler = ON; 

Аналогично, чтобы отключить все события, вы должны использовать:

  mysql> SET GLOBAL event_scheduler = OFF; 

После запуска планировщика событий вы можете просмотреть его состояние в списке процессов MySQL.

  mysql> ПОКАЗАТЬ ПРОЦЕССЛИСТ
 ...
      Id: 79
    Пользователь: event_scheduler
    Хост: localhost
      дБ: NULL
 Команда: Демон
    Время 12
   Состояние: ожидание в пустой очереди
    Информация: NULL 

Работа с событиями

Важно отметить, что при создании события оно может выполнять только те действия, для которых пользователь MySQL, создавший событие, имеет привилегии для выполнения. Некоторые дополнительные ограничения включают в себя:

  • Имена событий ограничены длиной до 64 символов.
  • Начиная с MySQL 5.1.8, имена событий не чувствительны к регистру; имя каждого события должно быть уникальным независимо от регистра.
  • События не могут быть созданы, изменены или удалены другим событием.

Вы не можете ссылаться на сохраненную функцию или пользовательскую функцию при настройке расписания событий.

Создание событий

В следующем примере создается событие:

DELIMITER |

CREATE EVENT myevent
    ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR
    DO
      BEGIN
        UPDATE mytable SET mycol = mycol + 1;
      END |

DELIMITER ;

Это событие будет запущено один раз, через час после его создания. Операторы BEGINEND Поскольку точка с запятой необходима для завершения оператора UPDATECREATE EVENT

Вы можете просмотреть список всех существующих событий с SHOW EVENTS

  mysql> ПОКАЗАТЬ СОБЫТИЯ
 ********************** 1. ряд **********************
                   Db: mysql
                 Имя: Myevent
              Определитель: dbuser @ localhost
            Часовой пояс: СИСТЕМА
                 Тип: ОДИН РАЗ
           Выполнить в: 2011-10-26 20:24:19
       Значение интервала: NULL
       Интервальное поле: NULL
               Начинается: NULL
                 Концы: NULL
               Статус: ВКЛЮЧЕНО
           Оригинатор: 0
 character_set_client: utf8
 collation_connection: utf8_general_ci 

После того, как событие истекло, оно будет автоматически удалено, если вы явно не указали иное с предложением ON COMPLETION

 CREATE EVENT myevent
    ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR
    ON COMPLETION PRESERVE
    DO
      BEGIN
        UPDATE mytable SET mycol = mycol + 1;
      END |

В этом примере, даже если событие истекло, оно все равно будет сохранено в базе данных, что позволит вам позже изменить его и запустить, или, возможно, вы просто захотите сохранить его для справки.

Чтобы навсегда удалить событие самостоятельно, вы можете использовать DROP EVENT

 DROP EVENT myevent;

Чтобы указать повторяющееся событие, вы должны использовать предложение EVERY

 CREATE EVENT myevent
    ON SCHEDULE EVERY 1 HOUR
    DO
      BEGIN
        UPDATE mytable SET mycol = mycol + 1;
      END |

И вместо того, чтобы иметь событие, которое выполняется один раз или навсегда, вы также можете запланировать повторяющееся событие, которое будет действительным только в течение определенного периода времени, используя предложения STARTEND

 CREATE EVENT myevent
    ON SCHEDULE EVERY 1 HOUR
    STARTS CURRENT_TIMESTAMP + INTERVAL 1 DAY
    ENDS CURRENT_TIMESTAMP + INTERVAL 1 YEAR
    DO
      BEGIN
        UPDATE mytable SET mycol = mycol + 1;
      END |

В этом примере повторяющееся событие начнется завтра и будет продолжаться каждый час в течение всего года.

Что касается времени, указанный интервал может быть YEARMONTHWEEKDAYHOURMINUTESECOND Имейте в виду, что ключевые слова приведены в единственном числе; писать что-то вроде INTERVAL 5 MINUTE

Обновление событий

Если вы хотите изменить поведение существующего события, а не удалять его и создавать заново, вы можете использовать ALTER EVENT Например, чтобы изменить расписание предыдущего события, которое будет запускаться каждый месяц, начиная с некоторой даты в будущем в 1 час ночи, вы должны использовать следующее:

 ALTER EVENT myevent
    ON SCHEDULE EVERY 1 MONTH
    STARTS '2011-12-01 01:00:00' |

Чтобы обновить событие с другим набором запросов, вы должны использовать:

 ALTER EVENT myevent
    DO
      BEGIN
        INSERT INTO mystats (total)
          SELECT COUNT(*) FROM sessions;
        TRUNCATE sessions;
      END |

Чтобы переименовать событие, вы должны указать предложение RENAME

 ALTER EVENT myevent
    RENAME TO yourevent;

Планирование публикации блога

Чтобы я мог показать вам практический пример, допустим, у вас есть блог, и вы хотите запланировать публикацию сообщений в будущем. Одним из способов достижения этого является добавление метки времени и опубликованного флага в записи базы данных. Сценарий cron будет выполняться раз в минуту, чтобы проверять временные метки и устанавливать флажки для всех публикаций, которые должны быть опубликованы. Но это не кажется очень эффективным. Другой способ добиться этого — использовать события MySQL, которые будут срабатывать, когда вы захотите опубликовать сообщение.

Ваша форма записи в блоге может иметь флажок, который, если установлен, указывает, что это запланированная запись. Кроме того, в форме будут поля ввода для ввода даты и времени публикации сообщения. Принимающий скрипт будет отвечать за добавление записи блога в базу данных и управление событиями для ее планирования, если это не будет немедленная публикация. Соответствующий код выглядит следующим образом:

 <?php
// establish database connection and filter incoming data
// ...

// insert blog post with pending status, get id assigned to post
$query = "INSERT INTO blog_posts (id, title, post_text, status) 
    VALUES (NULL, :title, :postText, 'pending')";
$stm = $db->prepare($query);
$stm->execute(array(":title" => $title, ":postText" => $text));
$id = $db->lastInsertId();

// is this a future post?
if (isset($_POST["schedule"], $_POST["time"])) {
    $scheduleDate = strtotime($_POST["time"]);

    $query = "CREATE EVENT publish_:id
    ON SCHEDULE AT FROM_UNIXTIME(:scheduleDate)
    DO
      BEGIN
        UPDATE blog_posts SET status = 'published' WHERE id = :id;
      END";
    $stm = $db->prepare($query);
    $stm->execute(array(":id" => $id, ":scheduleDate" => $scheduleDate));
}
// this is not a future post, publish now
else {
    $query = "UPDATE blog_posts SET status = 'published' WHERE id = :id";
    $stm = $db->prepare($query);
    $stm->execute(array(":id" => $id));
}

Когда сообщение хранится в базе данных, оно сохраняется с ожидающим статусом. Это дает вам возможность запланировать событие, если это запланированное сообщение, в противном случае статус может быть немедленно обновлен до опубликованного.

Если вам нужно будет отредактировать сообщение позже, вы можете удалить событие с помощью DROP EVENT IF EXISTS

Резюме

Теперь у вас должно быть четкое представление о том, что такое события MySQL, а также о том, как создавать собственные события и управлять ими. Хотя события не являются заменой для заданий cron или запланированных задач, поскольку события не могут выполнять внешний код, такой как сценарии PHP, они являются полезной альтернативой для зависящих от времени задач, специфичных для базы данных MySQL. Как всегда, если вы заинтересованы в получении дополнительной информации, обязательно ознакомьтесь с официальной документацией .

Изображение через Гарся / Shutterstock