前言
在某些特定的问题排查场景下,或者需要复现问题,我们可能需要开启general log 来查看 MySQL 实时运行的 SQL 语句,以此来缩小问题的范围。general log 会记录所有的SQL语句,无论语句是否正确执行或者是由于语法错误而终止执行。同时开启 general log 在实例负载比较大的情况下了能会对服务器性能产生影响,这里推荐一个好用的工具,它基于 MySQL 协议的抓包工具,实时抓取 MySQL Server 端的请求,并格式化输出。
工具安装
安装必要的依赖
yum install gcc gcc-c++ cmake libpcap-devel glib2-devel libnet-devel -y
安装命令
git clone https://github.com/Qihoo360/mysql-sniffer.git
cd mysql-sniffer
(base) [root@ip-10-0-0-22 mysql-sniffer]# ll
total 20
-rw-r--r-- 1 root root  272 Jan 23 08:58 CMakeLists.txt
drwxr-xr-x 2 root root   20 Jan 23 08:58 include
drwxr-xr-x 2 root root  126 Jan 23 08:58 lib
drwxr-xr-x 4 root root  321 Jan 23 08:58 libnids-1.24
-rw-r--r-- 1 root root 1066 Jan 23 08:58 LICENSE
drwxr-xr-x 4 root root  100 Jan 23 09:01 proj
-rw-r--r-- 1 root root 4298 Jan 23 08:58 README_CN.md
-rw-r--r-- 1 root root 2611 Jan 23 08:58 README.md
drwxr-xr-x 2 root root  242 Jan 23 09:01 src
(base) [root@ip-10-0-0-22 mysql-sniffer]# cd src/
(base) [root@ip-10-0-0-22 src]# ls
CMakeLists.txt  mysql-dissector.c  session.cpp  sniff-config.cpp  sniff-log.cpp  util.c
main.c          mysql-dissector.h  session.h    sniff-config.h    sniff-log.h    util.h
修改 CMakeLists.txt
ADD_EXECUTABLE(mysql-sniffer ${SRC_LIST})
TARGET_LINK_LIBRARIES(mysql-sniffer optimized
    libnidstcpreasm.a
    libpthread.so.0 #添加这一行
    libnet.a 
    libpcap.a
    libglib-2.0.a 
    libgthread-2.0.a
    librt.so)
   
TARGET_LINK_LIBRARIES(mysql-sniffer debug
    libnidstcpreasm-dbg.a
    libpthread.so.0 #添加这一行
    libnet.a 
    libpcap.a
    libglib-2.0.a
    libgthread-2.0.a
    librt.so)
然后执行下面的命令:
mkdir proj
cd proj
cmake ../
make
如何使用
查看帮助
(base) [root@ip-10-0-0-22 bin]# pwd
/root/mysql-sniffer/proj/bin
(base) [root@ip-10-0-0-22 bin]# ./mysql-sniffer -h
Usage ./mysql-sniffer [-d] -i eth0 -p 3306,3307,3308 -l /var/log/mysql-sniffer/ -e stderr
         [-d] -i eth0 -r 3000-4000
         -d daemon mode.
         -s how often to split the log file(minute, eg. 1440). if less than 0, split log everyday
         -i interface. Default to eth0
         -p port, default to 3306. Multiple ports should be splited by ','. eg. 3306,3307
            this option has no effect when -f is set.
         -r port range, Don't use -r and -p at the same time
         -l query log DIRECTORY. Make sure that the directory is accessible. Default to stdout.
         -e error log FILENAME or 'stderr'. if set to /dev/null, runtime error will not be recorded
         -f filename. use pcap file instead capturing the network interface
         -w white list. dont capture the port. Multiple ports should be splited by ','.
         -t truncation length. truncate long query if it's longer than specified length. Less than 0 means no truncation
         -n keeping tcp stream count, if not set, default is 65536. if active tcp count is larger than the specified count, mysql-sniffer will remove the oldest one
实时抓取某端口信息并打印到屏幕
(base) [root@ip-10-0-0-22 bin]# ./mysql-sniffer -i eth0 -p 3306
查看 MySQL 中真实执行的SQL 语句
mysql> shw databases; # 即使错误的语句也会被记录
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'shw databases' at line 1
mysql> show databases;
+-----------------------+
| Database              |
+-----------------------+
| information_schema    |
| dr                    |
| geek                  |
| mydumper              |
| mysql                 |
| performance_schema    |
| rudonx                |
+-----------------------+
7 rows in set (0.04 sec)
mysql> use rudonx
Reading table information for completion of table 
……
Database changed
mysql> show tables;
+------------------+
| Tables_in_rudonx |
+------------------+
| gk_37            |
| rudonx           |
| t1               |
| t11              |
| test             |
+------------------+
5 rows in set (0.04 sec)
查看 sniffer 输出
2022-01-23 17:50:36      rudonx  10.0.0.22       NULL            34ms             1      select @@version_comment limit 1
2022-01-23 17:50:47      rudonx  10.0.0.22       NULL            34ms             0      shw databases
2022-01-23 17:50:51      rudonx  10.0.0.22       NULL            35ms            12      show databases
2022-01-23 17:50:55      rudonx  10.0.0.22       NULL            35ms             1      SELECT DATABASE()
2022-01-23 17:50:55      rudonx  10.0.0.22       rudonx          34ms             0      use rudonx
2022-01-23 17:50:55      rudonx  10.0.0.22       rudonx          35ms            12      show databases
2022-01-23 17:50:55      rudonx  10.0.0.22       rudonx          35ms             5      show tables
2022-01-23 17:51:03      rudonx  10.0.0.22       rudonx          34ms             5      show tables
注 :输出格式为:时间,访问用户,来源 IP,访问 Database,命令耗时,返回数据行数,执行语句。
抓取某端口信息并打印到文件
运行命令如下:
(base) [root@ip-10-0-0-22 bin]# ./mysql-sniffer -i eth0 -p 3306 -l /tmp
查看文件输出:
(base) [root@ip-10-0-0-22 tmp]# tail -f 3306.log 
2022-01-23 18:00:06      rudonx  10.0.0.22       NULL            31ms             1      select @@version_comment limit 1
2022-01-23 18:00:18      rudonx  10.0.0.22       NULL            30ms             1      select 1
2022-01-23 18:00:30      rudonx  10.0.0.22       NULL            38ms            12      show databases
2022-01-23 18:00:48      rudonx  10.0.0.22       NULL            31ms             1      select * from rudonx.rudonx
2022-01-23 18:01:13      rudonx  10.0.0.22       NULL            31ms            61      show tables
注:-l 指定日志输出路径,日志文件将以 port.log 命名
实时抓取多个端口信息并打印到文件
示例命令如下:
(base) [root@ip-10-0-0-22 bin]# ./mysql-sniffer -i eth0 -p 3306,3307,3310 -l /tmp
注::-l 指定日志输出路径,-p 指定需要抓取的端口列表逗号分割。日志文件将以各自 port.log 命名。
使用注意事项
- 先运行./mysql-sniffer 命令,然后在连接MySQL,才可以抓取的到相关信息。
 - 使用该工具有一定的丢包几率。
 
如果您有其他问题,欢迎您联系火山引擎技术支持服务

