MYSQL 5.5 Event
12.01.09 | ||
1. MySQL Event
이벤트는 스케쥴에 따라 작업을 수행한다. ORACLE 의 ‘Job’ 이나 ‘Scheduler’ 와 동일한 기능을 한다.
기본적으로 Unix 의 crontab (cron job 으로 알려짐) 이나 Windows 의 Task Scheduler 와도 비슷하다.
MySQL Event 는 다음과 같은 특징을 가진다.
l MySQL Event 는 name 과 schema 로 구분된다.
l events 의 수행방법은 one-time (일회성) 이나 recurrent (주기적인) 가 될 수 있다.
recurrent 의 기본셋팅은 create 시점에 바로 수행되며, disabled 나 drop 되기 전까지 반복수행된다.
l 반복되는 event 를 interval 안에 종료하지 않으면, 동시수행되는 결과가 생길 수 있다.
이를 회피하기 위한 방안으로 GET_LOCK() function 을 사용할 수 있다.
l event 의 default definer 는 event 가 변경되지 않은 한 (alterd) 생성한 유저이다. alterd event 의
경우 definer 는 alter 구문을 수행한 유저이다.
2. Event Scheduler Configuration
Event 는 ‘event scheduler thread’ 에 의해 수행된다. event scheduler 의 thread 와 현재상태는 ‘event’ 권한을 가진 유저의 ‘show processlist’ 결과로 알 수 있다.
Global ‘event_scheduler’ system variable 은 event scheduler 의 사용가능 여부를 결정한다. 이 값은 3가지 값을 가진다.
l OFF – Event Scheduler 는 정지되어 있음. show processlist 결과를 볼 수 없다. event_scheduler 의 기본 값이다.
l ON – Event Scheduler 가 시작되어 있음.
l DISABLED – Event Scheduler 가 수행 불가능함을 의미. 이 상태는 runtime 에 변경하지 못한다.
event scheduler 의 비활성화 (disabled) 는 다음과 같은 방법을 사용할 수 있다.
l Starting option : --event-scheduler=DISABLED
l my.cnf : in a [mysqld] section : event_scheduler=DISABLED
event_scheduler 의 상태는 ON | OFF | 1 (ON) | OFF (0) 과 같은 Value 로도 컨트롤 할 수 있다.
3. Event Syntax
A. CREATE EVENT
<one-time style> create event myevent1 on schedule at ‘2011-01-10 15:00:00’ do insert into test.totalse values(‘myevent1’,now()); <recurrent style> #1 CREATE EVENT myevent2 on schedule at current_timestamp + interval 1 hour do insert into test.totalse values(‘myevent2’,now()); #2 CREATE EVENT myevent3 on schedule every 1 hour do insert into test.totalse values(‘myevent3’,now()); |
B. ALTER EVENT
alter event myevent 3 on schedule every 2 hour starts current_timestamp + interval 4 hour; alter event myevent3 disable; alter event myevent3 rename to myevent5; alter event a.myevent3 rename to b.myevent3; |
C. DROP EVENT
DROP EVENT [IF EXISTS] EVENT_NAME |
4. Event Metadata
Event 의 Metadata 를 확인하는 방법은 다음과 같다.
l mysql.event 를 조회
l information_schema.events 를 조회
l show create events 의 사용
l show events 를 사용
5. The Event Scheduler and MySQL Privilleges
global event_scheduler system variable 을 수정하기 위해서는 super 권한이 필요하다.
event 는 이를 정의한 definer 의 권한을 가지고 수행된다. 때문에 definer 가 필요한 권한이 없는 경우 아무 동작을 하지 못한다.
6. Event 의 사용 (실습)
<event 를 사용할 user 생성>
mysql> grant insert, event on *.* to 'hello'@'localhost' identified by 'hi'; Query OK, 0 rows affected (0.00 sec) |
<event 가 사용할 테이블 생성>
mysql> use test_case; Database changed mysql> create table test(dt date); Query OK, 0 rows affected (0.03 sec) |
<create event>
[mysql@dg1 mysql]$ ./bin/mysql -uhello –p mysql> create event myevent -> on schedule every 1 second -> do insert into test_case.test values(now()); |
위 상태에서는 event 가 동작하지 않는다. system variable ‘event_scheduler’ 를 ‘on’ 으로 변경해야 한다.
mysql> set global event_scheduler=on; Query OK, 0 rows affected (0.00 sec) mysql> select * from test_case.test; +------------+ | dt | +------------+ | 2012-01-10 | | 2012-01-10 | | 2012-01-10 | | 2012-01-10 | | 2012-01-10 | | 2012-01-10 | +------------+ |
<alter event>
mysql> alter event test_case.myevent disable; Query OK, 0 rows affected (0.00 sec) mysql> select name, status from event; +---------+----------+ | name | status | +---------+----------+ | myevent | DISABLED | +---------+----------+ 1 row in set (0.00 sec) |
<Metadata>
- mysql.event
mysql> select db, name, body from event; +-----------+---------+------------------------------------------+ | db | name | body | +-----------+---------+------------------------------------------+ | test_case | myevent | insert into test_case.test values(now()) | +-----------+---------+------------------------------------------+ 1 row in set (0.00 sec) |
- information_schema.events
mysql> select event_schema, event_name, event_body, event_definition from events; +--------------+------------+------------+------------------------------------------+ | event_schema | event_name | event_body | event_definition | +--------------+------------+------------+------------------------------------------+ | test_case | myevent | SQL | insert into test_case.test values(now()) | +--------------+------------+------------+------------------------------------------+ 1 row in set (0.00 sec) |
- show events
mysql> show events\G *************************** 1. row *************************** Db: test_case Name: myevent Definer: root@localhost Time zone: SYSTEM Type: RECURRING Execute at: NULL Interval value: 1 Interval field: SECOND Starts: 2012-01-10 13:49:03 Ends: NULL Status: DISABLED Originator: 1 character_set_client: utf8 collation_connection: utf8_general_ci Database Collation: latin1_swedish_ci 1 row in set (0.00 sec) |
- show create event
mysql> show create event myevent\G *************************** 1. row *************************** Event: myevent sql_mode: time_zone: SYSTEM Create Event: CREATE DEFINER=`root`@`localhost` EVENT `myevent` ON SCHEDULE EVERY 1 SECOND STARTS '2012-01-10 13:49:03' ON COMPLETION NOT PRESERVE DISABLE DO insert into test_case.test values(now()) character_set_client: utf8 collation_connection: utf8_general_ci Database Collation: latin1_swedish_ci 1 row in set (0.00 sec) |
7. Latency in executing event
가정 : 1 (MySQL 이 shutdown 되어 있는 상황)
여기서의 가정사항은 인터벌에 대해 수행 못한 동작들이 누적되지 않을까 하는 것이다.
다시 말해 1분마다 수행이 되는 작업이 있는데 중간에 3분의 shutdown 이 있었다면, MySQL startup 후에
3번의 작업이 한번에 호출되나 하는 것이다.
확인을 위해 1분마다 수행되는 test 테이블에 now() 값을 insert 하는 event 를 만들었다.
추가로 event_scheduler system variable 은 my.cnf 수정을 통해 on 으로 수정한 상태이다.
mysql> select * from test_case.test; +---------------------+ | dt | +---------------------+ | 2012-01-10 16:08:48 | | 2012-01-10 16:09:48 | | 2012-01-10 16:10:48 | | 2012-01-10 16:11:48 | | 2012-01-10 16:19:48 | | 2012-01-10 16:20:48 | | 2012-01-10 16:21:48 | | 2012-01-10 16:22:48 | | 2012-01-10 16:23:48 | | 2012-01-10 16:24:48 | | 2012-01-10 16:25:48 | | 2012-01-10 16:26:48 | +---------------------+ 12 rows in set (0.00 sec) |
결과를 보면 shutdown 이 발생했던 시각에 대해 단순히 event 가 호출되지 않았음을 알 수 있다.
가정 : 2 (Table Lock 경합)
여기서의 가정사항은 MySQL 의 작업을 이루는 SQL 이 Table Lock 경합으로 인해 지연되는 상황이다.
MySQL 은 CTAS, Insert-select 작업 시 CTAS 의 S 의 테이블, INSERT-SELECT 의 SELECT 테이블에 대해 UPDATE, DELETE 하지 못한다.
아래 예제에서는 myevent4 라는 event 를 사용하였다.
이 테이블은 test3 (258만건) 의 데이터를 하나 삭제하고, 타임정보를 test4 에 insert 하는 event 이다.
CTAS 를 이용해 test3 테이블을 test5 로 복제하는 경우 test4 에 기록된 타임정보가 어떻게 되는가를 보겠다.
mysql> set global event_scheduler=on; Query OK, 0 rows affected (0.00 sec) mysql> create event myevent4 on schedule every 1 second -> do -> begin -> delete from test3 limit 1; -> insert into test4 values(now()); -> end| Query OK, 0 rows affected (0.00 sec) mysql> create table test5 as select * from test3; Query OK, 2586579 rows affected (15.90 sec) Records: 2586579 Duplicates: 0 Warnings: 0 mysql> set global event_scheduler=off; Query OK, 0 rows affected (0.00 sec) mysql> select * from test4; +---------------------+ | dt | +---------------------+ ~~ (중략) ~~ | 2012-01-11 10:49:40 | | 2012-01-11 10:49:57 | | 2012-01-11 10:49:57 | | 2012-01-11 10:49:57 | | 2012-01-11 10:49:57 | | 2012-01-11 10:49:57 | | 2012-01-11 10:49:57 | | 2012-01-11 10:49:57 | | 2012-01-11 10:49:57 | | 2012-01-11 10:49:57 | | 2012-01-11 10:49:57 | | 2012-01-11 10:49:57 | | 2012-01-11 10:49:57 | | 2012-01-11 10:49:57 | | 2012-01-11 10:49:57 | | 2012-01-11 10:49:57 | | 2012-01-11 10:49:57 | | 2012-01-11 10:49:58 | ~~ (중략) ~~ |
test4 의 타임정보를 보니 10:49:57 데이터가 중첩되는 것을 알 수 있다.
event 자체를 매초 수행하도록 만들었고, 그 작업 내용도 시간이 안 걸리는 작업이기에 위 데이터의 의미는 작업에 지연이 발생했다는 것이다.
CTAS 를 다시 수행해보면서 다른 세션에서 processlist 를 확인해 보았다.
l CTAS 수행 전… mysql> show processlist; +-----+-----------------+-----------+-----------+---------+------+-----------------------------+------------------+ | Id | User | Host | db | Command | Time | State | Info | +-----+-----------------+-----------+-----------+---------+------+-----------------------------+------------------+ | 1 | root | localhost | test_case | Sleep | 3 | | NULL | | 435 | root | localhost | NULL | Query | 0 | NULL | show processlist | | 436 | event_scheduler | localhost | NULL | Daemon | 1 | Waiting for next activation | NULL | +-----+-----------------+-----------+-----------+---------+------+-----------------------------+------------------+ 3 rows in set (0.00 sec) l CTAS 수행 중… mysql> show processlist; +------+-----------------+-----------+-----------+---------+------+-----------------------------+---------------------------------------+ | Id | User | Host | db | Command | Time | State | Info | +------+-----------------+-----------+-----------+---------+------+-----------------------------+---------------------------------------+ | 1 | root | localhost | test_case | Query | 11 | Sending data | insert into test5 select * from test3 | | 435 | root | localhost | NULL | Query | 0 | NULL | show processlist | | 436 | event_scheduler | localhost | NULL | Daemon | 1 | Waiting for next activation | NULL | | 1024 | root | localhost | test_case | Connect | 11 | updating | delete from test3 limit 1 | | 1025 | root | localhost | test_case | Connect | 10 | updating | delete from test3 limit 1 | | 1029 | root | localhost | test_case | Connect | 9 | updating | delete from test3 limit 1 | | 1033 | root | localhost | test_case | Connect | 8 | updating | delete from test3 limit 1 | | 1034 | root | localhost | test_case | Connect | 7 | updating | delete from test3 limit 1 | | 1038 | root | localhost | test_case | Connect | 6 | updating | delete from test3 limit 1 | | 1042 | root | localhost | test_case | Connect | 5 | updating | delete from test3 limit 1 | | 1043 | root | localhost | test_case | Connect | 4 | updating | delete from test3 limit 1 | | 1047 | root | localhost | test_case | Connect | 3 | updating | delete from test3 limit 1 | | 1051 | root | localhost | test_case | Connect | 2 | updating | delete from test3 limit 1 | | 1052 | root | localhost | test_case | Connect | 1 | updating | delete from test3 limit 1 | +------+-----------------+-----------+-----------+---------+------+-----------------------------+---------------------------------------+ 14 rows in set (0.00 sec) |
event 가 수행한 sql (delete) 이 모두 대기중이며 Time 정보를 보면 해당 동작이 매초 수행되었음을 알 수 있다.
8. Cautions
table 을 지워도 이것과 연관된 event 는 삭제되지 않고 그대로 남아있다.
추가로 status 가 disable 되지도 않는다.
mysql> show tables; Empty set (0.00 sec) mysql> show events; +-----------+----------+----------------+-----------+-----------+------------+----------------+----------------+---------------------+------+---------+------------+----------------------+----------------------+--------------------+ | Db | Name | Definer | Time zone | Type | Execute at | Interval value | Interval field | Starts | Ends | Status | Originator | character_set_client | collation_connection | Database Collation | +-----------+----------+----------------+-----------+-----------+------------+----------------+----------------+---------------------+------+---------+------------+----------------------+----------------------+--------------------+ | test_case | myevent | root@localhost | SYSTEM | RECURRING | NULL | 1 | MINUTE | 2012-01-10 15:57:48 | NULL | ENABLED | 1 | utf8 | utf8_general_ci | latin1_swedish_ci | | test_case | myevent1 | root@localhost | SYSTEM | RECURRING | NULL | 1 | SECOND | 2012-01-11 10:34:25 | NULL | ENABLED | 1 | utf8 | utf8_general_ci | latin1_swedish_ci | | test_case | myevent2 | root@localhost | SYSTEM | RECURRING | NULL | 1 | SECOND | 2012-01-11 10:34:44 | NULL | ENABLED | 1 | utf8 | utf8_general_ci | latin1_swedish_ci | | test_case | myevent4 | root@localhost | SYSTEM | RECURRING | NULL | 1 | SECOND | 2012-01-11 10:46:38 | NULL | ENABLED | 1 | utf8 | utf8_general_ci | latin1_swedish_ci | +-----------+----------+----------------+-----------+-----------+------------+----------------+----------------+---------------------+------+---------+------------+----------------------+----------------------+--------------------+ 4 rows in set (0.00 sec) |
9. References
A. MySQL 5.5 Reference Manual | 18.4.1. Event Scheduler Overview |
http://dev.mysql.com/doc/refman/5.5/en/events-overview.html
B. MySQL 5.5 Reference Manual | 18.4.2. Event Scheduler Configuration |
http://dev.mysql.com/doc/refman/5.5/en/events-configuration.html
'Advanced MySQL' 카테고리의 다른 글
ORACLE Database Replay (0) | 2012.06.05 |
---|---|
MySQL Double Write Buffer (2012-02-21 발표 자료) (0) | 2012.03.04 |
MySQL 5.6 (Early Access Feature) (0) | 2012.01.03 |
MySQL Performance Optimization (Memory & Swap) (0) | 2011.11.17 |
Alter로 View의 definer 수정하는 방법 (0) | 2011.10.27 |