W życiu administratora są takie momenty, w których dobrze byłoby móc pewne czynności zautomatyzować. Wykonanie kopii zapasowej, rotacja logów, porządki na dysku. W przypadku baz danych jest podobnie. MySQL dobrze robi regularne uaktualnianie statystyk tabel (ANALYZE TABLE) czy defragmentacja (OPTIMIZE TABLE). Gdy stosujemy logowanie do tabel, dobrze by było także te tabele zrotować. Zazwyczaj tego typu zadania realizowane są przy pomocy skryptów uruchamianych z crona. Co jednak zrobić, gdy nie mamy do crona dostępu, bądź po prostu chcemy trzymać w bazie wszystko co bazy dotyczy?
MySQL 5.1 przyniósł ze sobą nowy mechanizm – events, czyli w wolnym tłumaczeniu – zdarzenia. Jest to kolejny proces działający w obrębie MySQL, którego zadaniem jest wykonywanie zleconych zadań. Na liście procesów wygląda on następująco:
*************************** 1. row ***************************
Id: 1
User: event_scheduler
Host: localhost
db: NULL
Command: Daemon
Time: 1
State: Waiting for next activation
Info: NULL
*************************** 2. row ***************************
Id: 32771
User: root
Host: localhost
db: db1
Command: Query
Time: 0
State: NULL
Info: SHOW PROCESSLIST
2 rows in set (0,00 sec)
Co ważne, domyślnie proces ten jest wyłączony. Jego zachowaniem steruje zmienna ‘event_scheduler`. Przyjmuje ona trzy wartości. OFF – scheduler jest wyłączony, dodatkowy proces jest zatrzymany. Jest to wartość domyślna, w każdej chwili można go włączyć uruchamiając polecenie:
Query OK, 0 rows affected (0,00 sec)
Druga wartość – ON. Scheduler jest włączony, proces działa i wykonuje zlecone zadania. Trzecia możliwość – DISABLED. To ustawienie wyłącza schedulera, proces jest zatrzymany. Co więcej, nie ma możliwości włączenia go w trakcie działania serwera. Konieczny jest restart serwera.
Jak w praktyce wygląda tworzenie zadania dla schedulera? Ogólna idea jest bardzo podobna do tworzenia funkcji i procedur. Popatrzmy.
mysql> CREATE EVENT backup_tab ON SCHEDULE EVERY 1 DAY STARTS '2011-09-30 00:00:01'
DO BEGIN
DROP TABLE IF EXISTS tab1_backup;
CREATE TABLE IF NOT EXISTS tab1_backup LIKE tab1;
INSERT INTO tab1_backup SELECT * FROM tab1;
END
$$
Query OK, 0 rows affected (0,01 sec)
mysql> DELIMITER ;
Powyższy kod tworzy event o nazwie backup_tab. Nie ma ustawionego definera, więc wykonywać się będzie na prawach aktualnie stosowanego użytkownika. W tym przypadku jest to ‘root’@’localhost’. Event wykonywać się będzie każdego dnia, pierwsze wywołanie odbędzie się sekundę po północy, 30 września. Zawartość nie należy do skomplikowanych – kasujemy tabelę o nazwie ‘tab1_backup’, tworzymy ją od nowa, tak aby struktura odpowiadała strukturze tabeli ‘tab1’, a następnie zapełniamy ją danymi zawartymi w tabeli ‘tab1’. Wszystko oczywiście opakowane w BEGIN i END, trzeba także pamiętać o zmianie delimitera na inny niż domyślny średnik.
Jeśli chodzi o opcje dotyczące definiowania momentu uruchamiania zadania, nie będę tu wchodził w szczegóły. Dokładne dane są w dokumentacji MySQL. Ogólnie mówiąc, można zadania definiować jako jednorazowe i powtarzające się. Można ustawić datę początku i końca wykonywania zadania. Można definiować czy zadanie powinno także być wykonywane na serwerach slave, czy też tylko na serwerze master.
Mechanizm ten jest na tyle precyzyjny, że swobodnie można definiować dosyć skomplikowane warunki. Trochę odbiega od tego, co czego przyzwyczaił cron, ale każdy, przy pomocy dokumentacji, powinien być w stanie go opanować.
W ramach eventu można oczywiście wywoływać funkcje i procedury, tak więc, jeśli tylko jest taka potrzeba, można wbudować w niego sporo kodu.
Informacje o tym, jakie eventy są zdefiniowane można uzyskać przy pomocy polecenia:
*************************** 1. row ***************************
Db: db1
Name: backup_tab
Definer: root@localhost
Time zone: SYSTEM
Type: RECURRING
Execute at: NULL
Interval value: 1
Interval field: DAY
Starts: 2011-09-30 00:00:01
Ends: NULL
Status: ENABLED
Originator: 1
character_set_client: latin2
collation_connection: latin2_general_ci
Database Collation: latin2_general_ci
*************************** 2. row ***************************
Db: db1
Name: testevent
Definer: root@localhost
Time zone: SYSTEM
Type: RECURRING
Execute at: NULL
Interval value: 5
Interval field: SECOND
Starts: 2011-09-10 21:02:08
Ends: NULL
Status: ENABLED
Originator: 1
character_set_client: latin2
collation_connection: latin2_general_ci
Database Collation: latin2_general_ci
2 rows in set (0,00 sec)
Informację w jaki sposób dany event został zdefiniowany można uzyskać przez:
*************************** 1. row ***************************
Event: backup_tab
sql_mode:
time_zone: SYSTEM
Create Event: CREATE EVENT `backup_tab` ON SCHEDULE EVERY 1 DAY STARTS '2011-09-30 00:00:01' ON COMPLETION NOT PRESERVE ENABLE DO BEGIN
DROP TABLE IF EXISTS tab1_backup;
CREATE TABLE IF NOT EXISTS tab1_backup LIKE tab1;
INSERT INTO tab1_backup SELECT * FROM tab1;
END
character_set_client: latin2
collation_connection: latin2_general_ci
Database Collation: latin2_general_ci
1 row in set (0,00 sec)
Zapraszam do zabawy z tym mechanizmem. Wbrew pozorom, jest to element bardzo przydatny do zarządzania serwerem MySQL.
Komentarze