Напомню, что включение штатного механизма query_log через файл конфигурации потребует перезапуска службы субд, что может занимать в некоторых случаях непрогнозируемое время. Если у вас есть рутовый дост к консоли севера, то можно сделать и без остановки:
> SET GLOBAL general_log_file = '/var/log/mysql/mysql.log';> SET GLOBAL general_log = 'ON';В файле mysql.log будет фиксироваться время запроса и сам запрос. Адрес клиента не увидим. Для того, чтобы фиксировать адрес клиента, хранить лог запросов нужно будет в в отдельной таблице mysql.general_log. Это уже будет немного другая настройка, для которой понадобится перезапуск. Но заметку я хотел написать не об этом.
Мы можем посмотреть содержимое запросов в сетевых пакетах через tcpdump. Сразу важное дополнение. Сработает это только для нешифрованных соединений с СУБД. Внутри локальной инфраструктуры это чаще всего так. Догадался я до этого не сам, а подсмотрел в очень старой заметке на opennet.
Запускаем на любой машине, через которую проходит трафик к MySQL серверу. Можно прямо на нём:
# tcpdump -i ens18 port 3306 -s 1500 -w tcpdump.outЖдём, когда посыпятся запросы. Можно с соседней машины подключиться и позадавать их:
# mysql -h 10.20.1.36 -u user01 -p> use database;> select * from users;В файле tcpdump.out будет собран raw трафик в формате pcap. Распарсить его можно тут же в консоли с помощью tshark:
# apt install tshark# tshark -r tcpdump.out -d tcp.port==3306,mysql -T fields -e mysql.query > query_log.outПолучится файл, где всё содержимое будет удалено, кроме mysql запросов. Но при этом останутся пустые строки. Чистим их:
# sed -i '/^$/d' query_log.outМожно поступить немного проще, преобразовав трафик сразу в обычные строки с помощью stdbuf и strings, а потом уже грепнуть по нужным запросам:
# tcpdump -i ens18 -s 0 -U -w - dst port 3306 | stdbuf -i0 -o0 -e0 strings | grep -iE --line-buffered "(SELECT|UPDATE|INSERT|DELETE|SET|SHOW|COMMIT|ROLLBACK|CREATE|DROP|ALTER)"Если нужны метки времени, то добавляем с помощью awk:
# tcpdump -i ens18 -s 0 -U -w - dst port 3306 | stdbuf -i0 -o0 -e0 strings | grep -iE --line-buffered "(SELECT|UPDATE|INSERT|DELETE|SET|SHOW|COMMIT|ROLLBACK|CREATE|DROP|ALTER)" | awk -W interactive '{print strftime("%F %T")" "$0}'Если хочется привязать запросы к IP адресам клиентов, то задача усложняется. Можно вывести содержимое пакетов вместе с остальной информацией, в том числе и об адресате пакета:
# tcpdump -i ens18 -s 0 -A -Q in port 3306Но дальше уже нетривиальная задача по при вязке адресата к самому запросу, так как между ними постоянно возникает разное количество строк с информацией в бинарном виде. Проще будет вернуться к pcap и оттуда пытаться это вытаскивать и сопоставлять. А если нет задачи сохранять в лог файле, можно просто забрать к себе на машину и посмотреть дамп через Wireshark. Там отлично видно и адресатов, и запросы.
❗️Если заметка вам полезна, не забудьте 👍 и забрать в закладки.
#mysql #tcpdump
