Logování MySQL slow queries + logrotation

Logování slow query neboli dotazů, jejichž zpracování trvá databázi déle než je stanovený long_query_time (ve výchozím nastavení 10 sekund) se hodí na serverech, na nichž běží jeden větší projekt nebo pár menších, do kterých vidí administrátor serveru a je v jejich zájmu aplikace optimalizovat. Nechat si logovat pomalé dotazy na sdíleném webhostingu může být pro admina zajímavé až ve chvíli, kdy Vám databázi bude někdo soustavně zatěžovat. Takže, jak na to?

O nastartování logování se postará direktiva log_slow_queries, zapsaná do konfiguračního souboru MySQL (/etc/my.cnf) někam pod direktivu serveru [mysqld]. Jak jsem psal výše, logují se dotazy, které trvají déle jak long_query_time, který zde můžeme také upravit. Příklad:

long_query_time = 5
log_slow_queries = /var/log/mysql_slow_queries.log

Log musíme taky vytvořit, takže např.

touch /var/log/mysql_slow_queries.log
chmod 660 /var/log/mysql_slow_queries.log
chown mysql. /var/log/mysql_slow_queries.log

Můžeme pokračovat restartem databáze, ale lepší bude použít mysqladmin (zvláště na vytížených serverech, kde se výpadek uživatelům nezamlouvá):

$ /usr/bin/mysqladmin flush-logs

Teď se nám dotazy trvající déle jak 5 sekund zapisůjí do logu, což je pěkné, ale bude-li jich moc, bude se nám log pěkně zaplňovat. Nechme jej tedy rotovat. K tomu využiji konfigurace v /etc/logrotate.d/mysql:

/var/log/mysqld_slow_queries.log {
     weekly
     rotate 3
     compress
     missingok
     notifempty
     create 660 mysql mysql
     portrotate
          /usr/bin/mysqladmin flush-logs
     endscript
}

Co k čemu slouží jistě najdete v manuálových stránkách (man logrotation), ale abych netrápil: weekly - rotujeme týdně, rotate 3 - uchováváme poslední 3 zálohy, compress - staré zálohy za "gzipujem", missingok - chybí-li log, tak nebudem křičet, notifempty - pokud je log prázdný, nebudem zbytečně rotovat, create ... - vytvoříme nový log s danými právy, postrotate - po rotaci upozorníme MySQL (/usr/bin/mysql flush-logs).

Problém může vyvolat chyba:

/usr/bin/mysqladmin: connect to server at 'localhost' failed
error: 'Access denied for user 'root'@'localhost' (using password: NO)'

Neznamená nic jiného, než že je přístup pro uživatel root do databáze pod heslem (je to přecejen rozumné). Aby nebylo nutné heslo pro mysqladmina zadávat do konfigurace logrotation, využijem služeb MySQL, který si čte informace z domovských adresářů a pěkně se podle nich řídí. Do /root/.my.cnf zadáme:

[mysqladmin]
password=TajneRootovoHeslo

a pro jistotu omezíme práva na minimum:

$ chmod 400 ~/.my.cnf

Teď po nás při volání mysqladmin pod uživatelem root nebude vyžadováno heslo (načte se z my.cnf) a tak můžeme vesele zapisovat do logu a ten následně rotovat.

Enjoy!

Zdroje: