Сообщить об ошибке.

MySQL: События EVENT и планировщик событий.

Содержание:


Включение/выключение планировщика событий MySQL.

События MySQL EVENT выполняются специальным потоком планировщика событий. При обращении к планировщику событий, на самом деле идет обращение к его потоку. За работу планировщика отвечает глобальная системная переменная event_scheduler, которая определяет, включен ли планировщик событий и работает ли он на сервере. Он имеет одно из следующих значений:

  • ON: планировщик событий запущен. Поток планировщика событий запускается и выполняет все запланированные события. ON - это значение event_scheduler по умолчанию.
  • OFF: Планировщик событий остановлен. Поток планировщика событий не запускается, не отображается в выходных данных SHOW PROCESSLIST; и запланированные события не выполняются.DISABLED: это значение отключает планировщик событий. Когда планировщик событий отключен, то поток планировщика событий не запускается. Кроме того, состояние планировщика событий нельзя изменить во время выполнения.

Посмотреть включен ли планировщик событий можно командой SHOW VARIABLES LIKE 'event_scheduler';

Если статус планировщика событий НЕ DISABLED, то переменную event_scheduler можно переключать между ON и OFF. Хотя ON и OFF имеют числовые эквиваленты, значение, отображаемое для event_scheduler с помощью SHOW VARIABLES;, всегда имеет значение OFF, ON или DISABLED. DISABLED не имеет числового эквивалента. По этой причине ON и `OFF обычно предпочтительнее, чем 1 и 0 при установке этой переменной:

SET GLOBAL event_scheduler = ON;
SET @@GLOBAL.event_scheduler = ON;
SET GLOBAL event_scheduler = 1;
SET @@GLOBAL.event_scheduler = 1;

Примечание: Включение планировщика при помощи установки переменной event_scheduler = ON не гарантирует его автоматическое включение после перезапуска сервера MySQL.

Чтобы планировщик событий автоматически включался при старте MySQL-сервера необходимо использовать один из следующих двух методов:

  • при запуске сервера --event-scheduler=ON, в качестве параметра командной строки;
  • включение переменной event_scheduler = ON в файле конфигурации сервера (my.cnf или my.ini в системах Windows), например, в разделе [mysqld].

Внимание! При отключенном планировщике event_scheduler = DISABLED можно создавать операторы управления событиями. Никаких предупреждений или ошибок в таких случаях не генерируется (при условии, что операторы сами по себе верны). Однако запланированные события не могут выполняться, пока для этой переменной не будет установлено значение ON (или 1). Как только это будет сделано, поток планировщика событий выполняет все события, условия планирования которых удовлетворены.

Создание запланированных событий в MySQL.

Синтаксис создания события EVENT в MySQL.

-- 
DROP EVENT IF EXISTS event_name
-- 
CREATE [DEFINER=user] EVENT [IF NOT EXISTS] 
    event_name ON SCHEDULE 
    AT timestamp [+ INTERVAL interval ... ] 
    | EVERY interval [STARTS ...][ENDS ...]
    [ON COMPLETION PRESERVE]
    [COMMENT 'string']
    DO [BEGIN]
               -- Тело события может содержать объявления 
               -- переменных `DECLARE`, циклы, например `LOOP`, 
               -- встроенные в MySQL и хранимые процедуры/функции и
               -- другие операторы структуры и/или управления потоком.          
          [END;]

Комментарии к синтаксису хранимых функции и процедур.

Событие связано со схемой. Если схема не указана как часть имени события event_name, то предполагается схема по умолчанию (текущая). Чтобы создать событие в определенной схеме, необходимо использовать синтаксис "имя_схемы.имя_события".

Инструкция CREATE EVENT требует привилегии EVENT для схемы, в которой должно быть создано событие. Если присутствует предложение DEFINER, требуемые привилегии зависят от значения пользователя.

Минимальные требования для действительного оператора CREATE EVENT следующие:

  • Ключевые слова CREATE EVENT плюс имя события event_name, которое однозначно идентифицирует событие в схеме базы данных.
  • Предложение ON SCHEDULE, которое определяет, когда и как часто выполняется событие.
  • Предложение DO, содержащее оператор SQL, который должен быть выполнен событием.

_Это пример минимального оператора CREATE EVENT:

CREATE EVENT myevent
    ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR
    DO
      UPDATE myschema.mytable SET mycol = mycol + 1;

Здесь создается событие с именем myevent. Это событие выполняется один раз - через час после его создания, путем выполнения инструкции SQL, которая увеличивает значение столбца mycol таблицы myschema.mytable на 1.

Имя события myevent должно быть действительным идентификатором MySQL с максимальной длиной 64 символа. Имена событий не чувствительны к регистру, поэтому в одной схеме не может быть двух событий с именами myevent и MyEvent. В целом, правила, определяющие имена событий, такие же, как и правила для имен хранимых подпрограмм.

DEFINER=user:

Инструкция DEFINER указывает учетную запись MySQL, которая будет использоваться при проверке прав доступа во время выполнения процедуры/функции. Если присутствует предложение DEFINER, то значением пользователя должна быть учетная запись MySQL, указанная как 'user_name'@'host_name', CURRENT_USER или CURRENT_USER(). Разрешенные значения пользователей зависят от имеющихся привилегий.

Если инструкция DEFINER опущена, то по умолчанию является пользователь, выполняющий оператор CREATE EVENT. Это то же самое, что явно указать DEFINER = CURRENT_USER.

Подробнее об инструкции DEFINER смотрите в материале "Хранимые процедуры и функции в БД MySQL".

IF NOT EXISTS:

Инструкция IF NOT EXISTS имеет то же значение что и для CREATE TABLE: если событие с именем event_name уже существует в той же схеме, то никаких действий не предпринимается и ошибка не возникает. (Однако в таких случаях генерируется предупреждение.)

COMMENT:

Инструкция COMMENT является расширением MySQL и может использоваться для описания события EVENT. Комментарий может быть любой строкой длиной до 64 символов. Текст комментария, являющийся строковым литералом, должен быть заключен в кавычки.

Например:

CREATE EVENT e_hourly
    ON SCHEDULE
      EVERY 1 HOUR
    COMMENT 'Clears out sessions table each hour.'
    DO
      DELETE FROM site_activity.sessions;

AT timestamp [+ INTERVAL interval ... ]:

Временная метка AT используется для одноразового события. Она указывает, что событие выполняется только один раз в дату и время, заданные отметкой времени timestamp, которая должна включать как дату, так и время, или должна быть выражением, которое разрешается в значение даты и времени. Для этой цели вы можете использовать значение типа DATETIME или TIMESTAMP. Если дата уже в прошлом, то появляется предупреждение: "Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. The event was dropped immediately after creation."

Можно использовать функцию CURRENT_TIMESTAMP, чтобы указать текущую дату и время. В таком случае событие действует, как только оно создано.

Чтобы создать событие, которое произойдет в какой-то момент в будущем относительно текущей даты и времени, например, выраженное фразой "через три недели", можно использовать необязательное предложение + INTERVAL interval. Часть interval состоит из двух частей, количества и единицы времени, и следует правилам синтаксиса, описанным в материале "Встроенные БД MySQL интервалы времени", за исключением того, что при определении события нельзя использовать микросекунды. С некоторыми типами интервалов могут использоваться комплексные единицы времени. Например, "две минуты и десять секунд" можно выразить как + INTERVAL '2:10' MINUTE_SECOND.

Также можно комбинировать интервалы. Например, AT CURRENT_TIMESTAMP + INTERVAL 3 WEEK + INTERVAL 2 DAY эквивалентно "через три недели и два дня". Каждая часть такого предложения должна начинаться с + INTERVAL.

EVERY interval [STARTS ...][ENDS ...]:

Чтобы повторять действия через равные промежутки времени, необходимо использовать предложение EVERY. За ключевым словом EVERY следует интервал interval, как описано в ключевом слове AT. Внимание! предложение + INTERVAL не используется с инструкцией EVERY. Например, EVERY 6 WEEK означает "каждые шесть недель".

Хотя предложения + INTERVAL не разрешены в инструкции EVERY, можно использовать те же комплексные единицы времени, которые разрешены в + INTERVAL.

Предложение EVERY может содержать необязательное предложение STARTS. За STARTS следует значение метки времени, которое указывает, когда действие должно начать повторяться, а также может использовать интервал + INTERVAL, чтобы указать количество времени "с этого момента". Например, EVERY 3 MONTH STARTS CURRENT_TIMESTAMP + INTERVAL 1 WEEK означает "каждые три месяца, начиная с одной недели". Точно так же можно выразить "каждые две недели, начиная с этого момента через шесть часов и пятнадцать минут" как EVERY 2 WEEK STARTS CURRENT_TIMESTAMP + INTERVAL '6:15' HOUR_MINUTE. Если не указывать STARTS, то это то же самое, что использовать STARTS CURRENT_TIMESTAMP, т. е. действие, указанное для события, начинает повторяться сразу после создания события.

Предложение EVERY может содержать необязательное предложение ENDS. За ключевым словом ENDS следует значение метки времени, которое сообщает MySQL, когда событие должно прекратить повторяться. С ключевым словом ENDS также можно использовать интервал + INTERVAL. Например, EVERY 12 HOUR STARTS CURRENT_TIMESTAMP + INTERVAL 30 MINUTE ENDS CURRENT_TIMESTAMP + INTERVAL 4 WEEK эквивалентно "каждые двенадцать часов, начиная с тридцати минут и заканчивая через четыре недели". Отсутствие использования ENDS означает, что событие продолжает выполняться бесконечно.

Ключевое слово ENDS поддерживает тот же синтаксис для комплексных единиц времени, что и STARTS. В инструкции EVERY можно использовать STARTS, ENDS, и то, и другое.

Если повторяющееся событие не завершается в течение интервала планирования, то результатом может быть одновременное выполнение нескольких экземпляров события. Если это нежелательно, то необходимо установить механизм для предотвращения одновременных экземпляров. Например, можно использовать функцию GET_LOCK() или блокировку строк или таблиц.

DO [BEGIN ... END]:

Предложение DO определяет действие, выполняемое событием, и состоит из оператора SQL. В качестве оператора действия для запланированного события можно использовать почти любой допустимый оператор MySQL, который можно использовать в хранимой процедуре. Например, следующее событие e_hourly удаляет все строки из таблицы сеансов один раз в час, где эта таблица является частью схемы site_activity:

CREATE EVENT e_hourly
    ON SCHEDULE
      EVERY 1 HOUR
    COMMENT 'Clears out sessions table each hour.'
    DO
      DELETE FROM site_activity.sessions;

Схема, к которой принадлежит событие, является схемой по умолчанию для ссылок на таблицы в предложении DO. Любые ссылки на таблицы в других схемах должны быть дополнены правильным именем схемы.

Как и в случае с хранимыми процедурами/функциями, в предложении DO можно использовать синтаксис составного оператора, используя ключевые слова BEGIN и END:

delimiter |
CREATE EVENT e_daily
    ON SCHEDULE
      EVERY 1 DAY
    COMMENT 'Saves total number of sessions then clears the table each day'
    DO
      BEGIN
        INSERT INTO site_activity.totals (time, total)
          SELECT CURRENT_TIMESTAMP, COUNT(*)
            FROM site_activity.sessions;
        DELETE FROM site_activity.sessions;
      END |
delimiter ;

В этом примере используется команда delimiter для изменения разделителя операторов. Подробнее о команда delimiter и блоке BEGIN ... END смотрите в материале "Хранимые процедуры и функции в БД MySQL".

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

delimiter |
CREATE EVENT e
    ON SCHEDULE
      EVERY 5 SECOND
    DO
      BEGIN
        DECLARE v INTEGER;
        DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN END;

        SET v = 0;

        WHILE v < 5 DO
          INSERT INTO t1 VALUES (0);
          UPDATE t2 SET s1 = s1 + 1;
          SET v = v + 1;
        END WHILE;
    END |
delimiter ;

Передать параметры напрямую в события или из них НЕВОЗМОЖНО, однако внутри события можно вызвать хранимую процедуру с параметрами:

CREATE EVENT e_call_myproc
    ON SCHEDULE
      AT CURRENT_TIMESTAMP + INTERVAL 1 DAY
    DO CALL myproc(5, 27);

Ограничения планировщика событий в MySQL.

Имена событий обрабатываются без учета регистра. Например, в одной базе данных не может быть двух событий с именами anEvent и AnEvent.

Событие не может быть создано, изменено или удалено из сохраненной программы, если имя события указано с помощью переменной. Событие также не может создавать, изменять или удалять сохраненные процедуры или триггеры.

Операторы DDL для событий запрещены, пока действует оператор LOCK TABLES.

Время события с использованием интервалов YEAR, QUARTER, MONTH и YEAR_MONTH определяется в месяцах. Те, которые используют любой другой интервал, разрешаются в секундах. Невозможно заставить события, запланированные на одну и ту же секунду, выполняться в заданном порядке. Кроме того, из-за округления, характера многопоточных приложений и того факта, что для создания событий и подачи сигнала об их выполнении требуется ненулевое время, события могут задерживаться на 1–2 секунды. Однако время, отображаемое в столбце LAST_EXECUTED таблицы INFORMATION_SCHEMA.EVENTS, всегда соответствует времени выполнения события с точностью до одной секунды.

Каждое выполнение операторов, содержащихся в теле события, происходит в новом соединении. Таким образом, в данном пользовательском сеансе эти операторы не влияют на количество операторов сервера, таких как Com_select и Com_insert (отображаются с помощью SHOW STATUS;). Однако такие счетчики обновляются в глобальной области.

События не поддерживают время, позднее окончания эпохи Unix. Это примерно начало 2038 года. Такие даты специально не разрешены Планировщиком событий.

Ссылки на хранимые функции, загружаемые функции и таблицы в предложениях ON SCHEDULE инструкций CREATE EVENT и ALTER EVENT не поддерживаются. Такие ссылки не допускаются.