You’ve got a production database server, and you can’t enable query logging… so how do you see the queries being executed against the database?
The answer: use a modified network sniffer to parse out the MySQL packets and decode them. You’ll have to do a little compiling, but it’ll be worth it. Note that this will not usually work for local connections, although you are welcome to try.
mysqlsniffer is a tcpdump clone specifically for dumping/sniffing/watching MySQL network protocol traffic over TCP/IP networks. mysqlsniffer is coded in C using the pcap library and works with MySQL version 4.0 and newer. mysqlsniffer is the only MySQL-specific network sniffer.
mk-query-digest also understands the MySQL protocol. It’s not a sniffer, though. It reads packet dumps from tcpdump like a slowlog. If you want to analyze queries from the wire (i.e. from network traffic), mk-query-digest is what you want.
For more information about the MySQL protocol read MySQL Internals ClientServer Protocol.
mysqlsniffer latest version Aug 18 2006 v1.2 (what’s new) via mysqlsniffer.tgz if you don’t want to follow the instructions below.
First, you need to install libpcap-dev (libpcap-devel for Redhat/Centos), which is the development library that allows an application to sniff network packets.
Ubuntu/Debian
sudo apt-get install libpcap-dev
Redhat/CentOS
sudo yum install libpcap-devel
Now let’s make a directory, download the source code and compile it
mkdir mysqlsniffer cd mysqlsniffer wget http://hackmysql.com/code/mysqlsniffer.tgz tar xvfz mysqlsniffer.tgz gcc -O2 -lpcap -o mysqlsniffer mysqlsniffer.c packet_handlers.c misc.c
At this point, we have a shiny new executable named mysqlsniffer in our source directory. You can copy it wherever you like (somewhere in the path would be useful)
To run mysqlsniffer, you need to specify the network interface that MySQL is listening on. For me, it’s eth0.
sudo /path/to/mysqlsniffer eth0
Ah, now there we are… all sorts of query information, without having to restart MySQL.
Here are the full options for the command:
Usage: mysqlsniffer [OPTIONS] INTERFACE OPTIONS: –port N Listen for MySQL on port number N (default 3306) –verbose Show extra packet information –tcp-ctrl Show TCP control packets (SYN, FIN, RST, ACK) –net-hdrs Show major IP and TCP header values –no-mysql-hdrs Do not show MySQL header (packet ID and length) –state Show state –v40 MySQL server is version 4.0 –dump Dump all packets in hex –help Print this
mysqlsniffer Capture Example
MySQL network protocol traffic from the command “mysqladmin -u root -h 127.0.0.1 processlist”:
Note: The capture interface here was lo instead of eth0.
mysqlsniffer listening for MySQL on interface lo port 3306 server > 127.0.0.1.3051: ID 0 len 70 Handshake (Caps: Get all column flags, Connect w/DB, Compression, ) 127.0.0.1.3051 > server: ID 1 len 38 Handshake (new auth) <user root db (null) max pkt 1073741824> (Caps: Long password, Get all column flags, LOAD DATA LOCAL, 4.1 protocol, Transactions, 4.1 authentication, ) server > 127.0.0.1.3051: ID 2 len 7 OK (Status: Auto-commit, ) 127.0.0.1.3051 > server: ID 0 len 17 COM_QUERY: show processlist server > 127.0.0.1.3051: ID 1 len 1 8 Fields ID 2 len 24 Field: ..Id ID 3 len 26 Field: ..User ID 4 len 26 Field: ..Host ID 5 len 24 Field: ..db ID 6 len 29 Field: ..Command ID 7 len 26 Field: ..Time ID 8 len 27 Field: ..State ID 9 len 26 Field: ..Info ID 10 len 5 End (Status: Auto-commit, ) ID 11 len 49 || 1 | root | localhost:3051 | NULL | Query | 0 | NULL | show processlist || ID 12 len 5 End (Status: Auto-commit, ) 127.0.0.1.3051 > server: ID 0 len 1 COM_QUIT mysqlsniffer exited cleanly. 17 MySQL packets captured (469 bytes)
Loads of stuff starts flying by… let’s filter it out a little more so we can just get the queries and not all the excess data.
$ sudo /path/to/mysqlsniffer –no-mysql-hdrs eth0 | grep COM_QUERY 192.168.73.1.2622 > server: COM_QUERY: SELECT @@sql_mode 192.168.73.1.2622 > server: COM_QUERY: SET SESSION sql_mode=” 192.168.73.1.2622 > server: COM_QUERY: SET NAMES utf8 192.168.73.1.1636 > server: COM_QUERY: SELECT @@SQL_MODE 192.168.73.1.1636 > server: COM_QUERY: SHOW FULL COLUMNS FROM `db2842_howto`.`wp_users`
Original source code and more information at:
http://hackmysql.com/mysqlsniffer
If you are running on a development server, it would be easier to just turn on query logging.