Dzisiejszym tematem będzie  jedno z pytań, które przewija się w statystykach wejść na bloga. Jak można debugować działanie MySQL? Jakie są dostępne narzędzia? Wbrew pozorom, pytanie to nie jest takie oczywiste i właściwie jest to temat na całą serię postów. Kiedyś pewnie się za to zabiorę, dziś tylko takie proste zestawienie. No więc, co i jak można zrobić?

W pewnym uproszczeniu można przyjąć, że są dwa rodzaje obciążenia serwera – CPU i IO. Po angielsku brzmi to ładnie – serwer może być cpu bound, albo IO bound, w zależności czy zapytania czekają na procesor, czy też na podsystem dyskowy. Oba rodzaje obciążenia wymagają innych sposobów na debugging.

Oczywiście, podstawowe informacje na temat rodzaju obciążenia serwera można uzyskać ze slowlogów, szczególnie rozszeżonych, dostępnych np. w Percona Server. To może być jednak niewystarczające. Co mamy jeszcze do dyspozycji? Jeśli chodzi o debugging obciążenia procesora, można zastosować np. oprofile – moduł do kernela, który zbiera dane o działających procesach i jest w stanie przygotować raporty dotyczące tego, jaki proces ile razy realizował wywołania funkcji. Jeśli biblioteki i binarki zawierają symbole, oprofile udostępni informację także o tym jakie konkretnie funkcje były przez proces wykonywane. Jeśli orientujemy się choć pobieżnie w kodzie źródłowym MySQL to mamy bardzo precyzyje informacje o tym, co jest wąskim gardłem w obecnej sytuacji. Jeśli nie mamy możliwości użycia oprofile (np. nie jesteśmy w stanie załadować modułu do kernela), pozostaje zawsze Poor Man’s Profiler i jego pochodne. Jest to skrypt shellowy, który przy użyciu GDB potrafi wygenerować zestawienie gdzie i ile czasu CPU dany proces spędza.

Jeśli chodzi o profilowanie obciążenia na dysku, to sprawa jest trochę trudniejsza – oba wcześniej wymienione narzędzia nie bardzo się przydadzą. Ze znanych mi rozwiązań, które mogą w takiej sytuacji pomóc (jeśli któryś z czytelników zna jakieś inne, prosiłbym o komentarz), pozostaje w zasadzie tylko ioprofile z zestawu narzędzi Aspersa. Potrafi on przygotować zestawienie ile razy jaki plik był czytany, zapisywany itp. W połączeniu z innodb_file_per_table można w ten sposób określić, która tabela generuje takie obciążenie dysku.

Co jeszcze? Pewne informacje można uzyskać przy pomocy profilera zapytań wbudowanego w MySQL (set profiling=1), pisałem o tym w jednym z pierwszych postów na blogu. Dodatkowo, MySQL 5.5 wprowadził Performance Schema – bazę, w której gromadzone są informacje o obciążeniu serwera MySQL. Zestawienie to obejmuje np. listę locków i muteksów, które najdłużej blokują działanie serwera.

Jak widać, nie jest tak, że nie da się sprawdzić co piszczy pod maską serwera MySQL. Czasami nie jest to łatwe, czasami wymaga przygotowania odpowiedniego środowiska (np. odpowiednie skompilowanie całości tak, aby symbole pozostały w plikach binarnych i bibliotekach). Na szczęście, zazwyczaj da się dojść do bezpośredniej przyczyny problemów z wydajnością.