之前写过一个mysql 5.6如何跟踪在毫秒级记录sql日志的问题,当时是通过为输出全局日志加时间的方式来实现的,不是很精确。采用tcpdump的方式从网络层抓包记录的时间更精确。而且还有ip和端口记录
原理
使用tcpdump的网络抓包功能,从mysql客户端和服务器交互的网络数据中,直接输出sql语句,和网络包的相关信息。
实现功能
1、跟踪sql语句
可以输出所有客户端请求的sql
2、记录sql语句时间
可以输出微秒级的时间
3、分析sql语句的请求和应答时间
通过跟踪同一个原端口发送sql语句和接收数据包的间隔,可以实时跟踪分析sql语句的执行时间。与mysql profiling相比可以实时跟踪程序实际执行情况。
4、确认发起sql语句的进程
可以根据客户端源端口结合在客户端执行lsof 命令确认发起sql的进程
前提
mysql客户端和服务器之间不要开启加密传输,一般内网都不开。
在服务器有tcpdump权限
实现方式
使用perl写的解析脚本,直接帖就可以用,不需要保存。
#只输出sql tcpdump -i eth1 -s 0 -l -w - dst port 3306 | strings | perl -e ' while(<>) { chomp; next if /^[^ ]+[ ]*$/; if(/^(SELECT|UPDATE|DELETE|INSERT|SET|COMMIT|ROLLBACK|CREATE|DROP|ALTER|CALL)/i) { if (defined $q) { print "$q\n"; } $q=$_; } else { $_ =~ s/^[ \t]+//; $q.=" $_"; } }'
#记录时间,源和目的ip地址端口,tcp标志和sql tcpdump -i eth0 -Annn -s 0 -l port 3306 | strings | perl -e ' while(<>) { chomp; if(/^\d\d:\d\d:\d\d.\d{6} IP.+$/){ print "\n$_\t"; } if(/((SELECT|UPDATE|DELETE|INSERT|SET |COMMIT|ROLLBACK|CREATE|DROP|ALTER|CALL).+$)/i) { print "$1"; }else{ } }'
进阶
如果想更进一步解析,可以参考 https://github.com/nlitsme/xpcapperl 的项目 或者用perl的cpan包
Net::Packet::Dump
Net::Analysis
Net::TcpDumpLog
我简单搜了一下,这几个都可以试试。
© 2018, 新之助meow. 原创文章转载请注明: 转载自http://www.xinmeow.com