MySQL

индекс
230,83

Кто стоит за соединениями?

Периодически возникают ситуации, когда хочется понять, какой же процесс на сервере повинен за конкретное соединение с СУБД. К примеру, очень много соединений к базе и хочется узнать, откуда они идут. Либо, есть какие-то «тяжёлые» соединения (по которым какие тяжёлые запросы идут, которые тормозят всё).

Можно ли это вообще узнать эту информацию? Оказалось, что в этом нет ничего сложного! Однако, каждый раз руками устанавливать соответствие довольно муторно. Так почему бы не автоматизировать процесс?

Нет ничего проще!

Кто же вы, незнакомецы?


Итак, узнать, кто стоит за каким соединением в автоматическом варианте можно такой командой:

mysql -u<user> -p<password> -h<host> -e "SHOW PROCESSLIST;" | perl -lne 'print $1 unless !/(:\d+)/' | while read port; do netstat -tp | grep $port; done

Вывод будет примерно такой:

(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
tcp 0 0 server.local:44800 192.168.1.2:mysql ESTABLISHED 7476/mysql
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
tcp 0 0 server.local:35766 192.168.1.2:mysql TIME_WAIT -

Да, если запускать приведённую выше команду не из под root'а, будет некоторое количество шлака, как можно видеть выше. И, естественно, не будет возможности узнать процесс, запущенный от другого пользователя ;) В общем, без root'а толку мало.

Что дальше?


Итак, процесс узнан. Как понять, что он делает такого плохо?

Универсальные инструменты для анализа работы запущенного процесса (Гугл поможет с детальным описанием):
  • strace — что внутри?
  • netstat — какие соединения вообще есть у процесса?
P.S. В MySQL 5.1 есть великолепная таблица INFORMATION_SCHEMA.PROCESSLIST, откуда можно более гибко вытаскивать данные.
+3
23 июля 2010, 15:42
30

комментарии (17)

–6
TravisBickle #
Кто здесь?!!!
+1
toxa #
man mytop
0
zoxa #
вроде бы mytop умер уже давно… последнее изменение было в 2006 году
он зависит от более старой версии python, а на новую его не перепортировали
0
Min0r #
2007-й и зависит от Perl библиотек, а точнее от: DBI, Term::ReadKey, Time::HiRes, Term::ANSIColor. Актуален и сейчас.

Можно еще комментарии использовать в запросах SQL:
SELECT /* pid script_name*/ count(*) FROM `table`;
или
/* pid script_name*/ SELECT count(*) FROM `table`;
+3
Ikarr #
Кто же мы, незнакомецы?
+5
lexun #
Итак вся статься сводится к команде mysql -u -p -h -e «SHOW PROCESSLIST;» | perl -lne 'print $1 unless !/(:\d+)/' | while read port; do netstat -tp | grep $port; done, а остальное предлагается самим догуглить… супер!
0
gribozavr #
> И, естественно, не будет возможности узнать процесс, запущенный от другого пользователя

netstat -a
0
gvsmirnov #
egrep ниасилил?
0
zoxa #
Вот мои версии bash скрипта MyTop

0
zoxa #
офигеть, почему комментарий сам отправился?!
вот коды

/usr/bin/watch -n 3 «mysql -u<user> -p<password> [<db>] -h<host> -A -e 'SHOW PROCESSLIST'»

или полный список
/usr/bin/watch -n 3 «mysql -u<user> -p<password> [<db>] -h<host> -A -e 'SHOW FULL PROCESSLIST'»
0
Min0r #
Можно еще параметры соединения кинуть в .my.cnf ;)
0
zoxa #
Извиняюсь а про какие именно параметры идет речь?
Какие из них мошки помочь?
0
Min0r #
$ cat > ~/.my.cnf <<EOF
[client]
host = 127.0.0.1
user = root
password = password4root
EOF
$ chmod 600 ~/.my.cnf
$ mysql -A -e 'SHOW FULL PROCESSLIST'

Избавитесь от: -u -p -h
0
zoxa #
ааа эти…

Min0R у меня тогда встречный вопрос. а можно как-нибудь забить несколько host/login/password
Мне надо подключаться как минимум к 2-3м разным базам данных на разных хостах для проверки репликации и для тестирования, или так не получиться???

Мой выход из этой ситуации это создать пару shell скриптов которые выполняют предложенные мною строчки, поэтому я их не набираю ручками каждый раз
0
Min0r #
Shell хороший вариант, но в окружении bash можно строить алиасы на команды — очень хорошая фича.

Строим алиасы команд:

$ vim ~/.bashrc
#добавляем
alias mysql1='mysql -h 192.168.1.1 -uroot1 -ppassword4root1'
alias mysql2='mysql -h 192.168.1.2 -uroot2 -ppassword4root2'
alias mysql3='mysql -h 192.168.1.3 -uroot3 -ppassword4root3'

Сохраняемся и перегружаем сессию. Теперь у Вас будут доступны команды из bash, используйте Таб для автозаполнения: mysql, mysql1, mysql2, mysql3.

Далее предложил бы сразу вывести в приглашение mysql монитора имя сессии и БД, это можно сделать путем добавления дополнительных параметров в ~/.my.cnf:

$ vim ~/.my.cnf
#добавляем
[mysql]
prompt=mysql:\\u@\\h\\ \\d>

В результате Вы получите:
$ mysql
mysql:root@127.0.0.1 (none)>use mysql
Database changed
mysql:root@127.0.0.1 mysql>

Надеюсь без ошибок. )
0
Min0r #
И еще используйте screen для одновременного мониторинга состояния СУБД в реальном времени.
0
zoxa #
даааа, про алиасы я что то забыл. у меня просто скрипты с аналогичным текстом… Спасибо за совет, попробую переделать.

настройки промпта я использую.
могу посоветовать посмотреть еще на pager, очень полезно когда результаты запросы реально большие

<<<< .my.conf
[client]
default-character-set= utf8
#pager = less -niS
pager = less -iMSx4 -FX
prompt =(\u@\h) [\d]>
>>>> .my.conf

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.