Pull to refresh

Comments 27

хоть и активно использую MySQL, но про события не знал (видать еще не возникало ситуаций когда пригодилось бы), автору спасибо за статью, добавил в закладки
Кстати, очень хорошо подойдет для очистки базы от временных объектов вроде протухших сессий. Видимо, про events мало кто знает из разработчиков CMS — в каждой второй надо обязательно в крон повесить специальный скрипт.
Это, скорее всего, обусловлено не столько незнанием разработчиками mysql, сколько всеядностью этих самых CMS (большинство спокойно работает на 4.1, где этих самых ивентов еще не было), а поддерживать несколько способов самоочистки не выгодно (лень).
а не знает конечно потому что:
1. мало кто вообще обеспокоен при создании CMS о производительности БД, ибо в общем случае сайты на CMS не требуют этого в принципе;
2. CMS создают в первую очередь программисты, а БД это вообще отдельная песня;
3. ну и в силу самого MySQL евенты автоматом выключены в стандартной сборке, и естественно их хостеры включать не особо любят, так как в принципе не знают о такой штуке тоже. Да и к тому же чтобы разобраться как заставить нормально работать эвенты на 5.5 пришлось мне потратить пару часов, чтобы найти в 3000 страничных концептах MySQL что нужно для этого.
Как я понимаю, это типа триггера но только по расписанию? Интересно, почему ввели новую сущность, а не расширили синтаксис триггеров для поддержки событий по дате?
Это не совсем так. Триггер привязан к событию конкретной таблицы. А event выполняется просто по расписанию. И его инициирует сам сервер базы данных.
Думаю все же лучше по старинке, производить необходимые действия по cron.
Спасибо, добавил в избраное
Крон-задач в дампе не будет и при переезде их можно забыть. И при развертывании тоже все проще становится. Только решение становится не «кросс-субдшное»
отнюдь — все зависит от архитектуры. если к примеру у меня база лежит на одном серваке в одном конце света, а программный код на другом конце света, то крон, создавая его на том сервере, где лежат исходники ресурса, будет как минимум стучаться по сети к субдешному серваку, получать какие-то данные, их дополнительно обрабатывать и еще что-то с ними делать — а это тянет нагрузку на канал, если особенно дам надо сделать и разместить где-то еще. Да и можно заморочиться с правами, так чтобы системные операции выполнялись только на уровне БД, соответственно запретить любые коннекты извне к серверу БД, что даст дополнительные защитные маневры.
конечно категорично сказать что крон хуже нельзя, ибо он вполне по очевидным причинам в многих случаях выигрывает, но эвенты могут кое где и обойти крон.
А как посмотреть список запущенных событий?
Вот только это не запущенные события, а существующие. Поэтому надо обращать внимание еще на статус (ENABLED/DISABLED)
Скажите, а можно выполнять событие каждый день в 4:12, например (когда сервер не нагружен)? И чтобы время не «плыло». Из описанного синтаксиса непонятно.
Примерно так
CREATE EVENT `event_name`
ON SCHEDULE EVERY 1 DAY STARTS '2011-07-05 4:12:00'
ON COMPLETION NOT PRESERVE
ENABLE
COMMENT '' DO
CALL new_proc();
Спасибо!

Во всём этом пока смущает только один момент: практически ни в одном проекте не обойтись без скриптов (которые обслуживают не только БД), которые запускаются по планировщику. И иметь планировщик в двух разных местах (php и mysql) как-то уж очень сложно…

Сейчас я вызываю mysql-обновления из php. Наоборот, наверное, тоже можно (не уверен, но, кажется, можно). Но как-то совсем уж кажется извращением.

Поэтому зона применения подобных событий пока непонятна.
Сфера применения очевидна.
— очистка различных временных данных, архивирование таблиц (как в описанном случае)
— ETL операции, подготовка среза данных, чтоб не расчитывать их в процессе работы и не грузить систему (например счетчики или контрольные суммы)
В теории — понятно.

На практике делать это из PHP удобнее ещё потому, что в случае ошибки логи сохранятся штатной системой обработки ошибок, встроенной во фреймворк (во многих такое есть).

Если же обвалится событие в MySQL (из-за того, что кто-то забыл изменить имя таблицы в процедуре), мне пока непонятно, как я об этом узнаю.
Ошибка осядет в логах. Обработкой лога MySQL могут заниматься другие приложения. Вы же мониторите хоть иногда медленные запросы например? Вот тоже самое и с ошибками планировщика.
Непонятно, почему разработчики это назвали событиями. Это ж задания (shedules).

В Firebird, например, EVENT — это событие, обрабатываемое на клиенте. Т.е. в триггере или процедуре создается событие (POST_EVENT), на клиенте срабатывает его обработчик, если клиент пожелал это событие принимать. Бывает полезно.
Это не задания. Задания — это jobs например
У них это называется event scheduler (планировщик событий), и это правильно.
Нам же проще называть их просто «события» :)
Можно поподробней про событие обрабатываемое на клиенте?
несовсем понятно, о чем речь.
на клиенте нужна поддержка серверных событий. Реализуется либо через API клиентской библиотеки fbclient.dll либо высокоуровневыми компонентами типа TIBEvent (Borland), TFIBEvent (FIB Plus).

продолжаю:

на клиенте «подписываемся» на событие

ib_event.RegeisterEvent('MyCustomEvent');


В хранимой процедуре или триггере вызываем событие

POST_EVENT 'MyCustomEvent';


на клиенте срабатывает обработчик

ib_event.OnEvent();


Да, хорошая вещичка, мне оно помогала чистить БД, от лишних записей. Запускается событие и выполняет различные условия, также интересны будут триггеры, процедуры и много других вкусностей.
Хотелось бы внести пару ложек дегтя в бочку меда. Начну из далека.
Как только в MySQL появились события, я очень обрадовался, так как привык работать с job в оракл и этой функциональности очень не хватало, однако. На последней конференции по MySQL (которую уже устроил Oracle) мы пообщались с разработчиками на тему, а как вам events в MySQL. На что получили крайне забавный ответ, ал-я «Вася иди сюда, расскажи как много багов у тебя в этом долбанном шедулере». Т.е. по мнению разоработчиков качество кода, который им достался в наследство, оставляет желать лучшего.
Events мы все таки заюзали. Ибо фича полезное а я верю в лучшее.

Первые проблемы начались когда MySQL 5.5.11 начал слегда подвисать из-за того, что не мог создавать новый бинарный лог, если имелись незавершенные транзакции. Механизм у нас был заюзан очень активно. Особенностью MySQL event scheduler состоит в том, что если событие не завершилось, то оно все равно стартует ещё раз, по этому страховку, защиту от дурака, надо делать самим. Изначально мы её не сделали, и при подвисании события запускались в геометрической прогрессии, убивая БД полностью.
Эту проблему мы решили, ну сами дураки — сами и исправились. Сделали что-то типа:

-----------------------------------------------------------------------------
drop event if exists ev_refresh_decline_structures;
delimiter $$
create event ev_refresh_decline_structures
on schedule every 10 second
comment 'Refresh decline data'
do
main_sql:
begin
declare v_eexl_id int(10);
call event_start(v_eexl_id, 'paynet.ev_refresh_decline_structures');
if v_eexl_id is null then leave main_sql; end if;
call refresh_decline_structures(500);
call event_finish(v_eexl_id, 'paynet.ev_refresh_decline_structures');
end
$$
delimiter ;
-----------------------------------------------------------------------------
drop procedure if exists event_start;
delimiter $$
create procedure event_start(out o_eexl_id int(10), i_event_name varchar(64))
main_sql:
begin
declare v_lock_is_set int(1);

select get_lock(i_event_name, 0)
into v_lock_is_set;

if coalesce(v_lock_is_set, 0) = 0 then
leave main_sql;
end if;

insert into event_execution_logs(event_name, start_date)
values (i_event_name, now());

set o_eexl_id = last_insert_id();
commit;
end
$$
delimiter ;
-----------------------------------------------------------------------------
drop procedure if exists event_finish;
delimiter $$
create procedure event_finish(i_eexl_id int(10), i_event_name varchar(64))
main_sql:
begin
declare v_lock_is_set int(1);

update event_execution_logs
set end_date = now()
where eexl_id = i_eexl_id;

commit;

select release_lock(i_event_name)
into v_lock_is_set;
end
$$
delimiter ;
-----------------------------------------------------------------------------

Таким образом мы запретили одновременный запуск событий, а так же стали мониторить время выполнения оных и частоту запуска.
Через месяц мы били сильно удивлены. Мы заметили, что одно событие, которые должно запускаться раз в день в 2 часа ночи, запускается через раз, через 2!!! Особенностью шедулера так же является то, что если время события прошло то оно не будет запущено ещё раз. вроде все логично, но на практике, шедулер просто ПРОПУСКАЕТ события, иногда совершенно по непонытным причинам. В качестве workaround мы переписали код процедур выполняемых событий. таким образом чтобы запускать их можно было чаще а само время реальной отработки они контролировали сами.
В общем — будьте внимательны не натыкайтесь на наши грабли.

З.Ы. ввиду всех этих непонятностей, мы приняли решение написать свой шедулер для MySQL который будет лишен всех этих неостатков на Javaб чего и вам желаем
Весьма полезные замечания. Спасибо! Кто предупрежден, тот вооружен.
Sign up to leave a comment.

Articles