一、概述
tcpdump在我们平时运维中充当了很重要的角色,对复杂问题的排查、分析起到了至关重要的作用,确实为运维中的一大利器。
用简单的话来定义tcpdump,就是:dump the traffic on a network,根据使用者的定义对网络上的数据包进行截获的包分析工具。本文主要从两个方面介绍tcpdump,首先是介绍下tcpdump的使用方式,然后介绍下tcpdump在mySQL数据库运维过程中具体实践,如果DBA能熟练的使用tcpdump,在运维工作中一定如虎添翼
二、参数介绍
命令格式:
1.-c:指定要抓取的包数量,抓取X个包后就停止。
2.-i:interface:指定tcpdump需要监听的窗口,默认会抓取第一个网络接口。指定为any代表抓取所有网卡上的包。
3.-P:指定要抓取的包是流入还是流出的包,具体值”in”、”out”和”inout”,默认为”inout”。
4.-s:设置显示前多少个字节的包内容(snaplength)。设置为0代表显示完整的包内容。
5.-v,-vv,-vvv:详细!更详细!再详细些!冗余输出包的信息。
6.-w:结果文件输出的位置。结果文件是以tcpdump的格式存储,可以用Wireshark工具解析。
expression表达式
一个基本的表达式单元格式为:”proto dir type”
类型type
host,net,port,portrange
例如:host 192.168.1.1,net 128.2,port 20
目标dir
src,dst,src or dst,src and dst
协议proto
tcp,udp,icmp,若未给定协议类型,则匹配所有可能的类型。
三、使用示例
-
截取所有192.168.94.128的主机收到和发出的所有数据包。
#tcpdump host 192.168.94.128
2. 监听指定主机192.168.94.128和指定网卡上的数据包
#tcpdump host 192.168.94.128 -i eth0
3. 监听指定网卡、端口的数据包
#tcpdump –i eth0 port 8080
4. 监听所有发送到192.168.94.128的数据包
#tcpdump -i eth0 dst host 192.168.94.128
5. 监听192.168.94.128和192.168.94.129或者192.168.94.130间的通讯包
#tcpdump -i eth0 host 192.168.94.128 and (192.168.94.129 or 192.168.94.130) - 监听本机3306端口的包,抓取完整包,并输出到tmp下
#tcpdump -s0 -vv port 3306 -w /tmp/hostname
.pcap
四、在MySQL中的应用
案例一
第一个想写的是mySQL的建链和断链过程,本人在实际运维过程中遇到过由于网络原因导致的建链异常的情况,当你怀疑网络有问题时可以通过tcpdump进行分析。那我们先来一起看下MySQL的的三次握手和四次挥手吧(关于TCP协议中的三次握手和四次挥手的原理需要自行查询)。
首先我们在MySQL服务器上执行监听命令: tcpdump -i eth0 -s0 port 3306 -w 1513.pcap
可以看到我们一共抓了44个包,我们将pcap文件下载到电脑后,用Wireshark进行分析。
从图上可以看出192.168.94.1是客户端,192.168.94.128是MySQL服务端,第一个包是客户端向服务端发送了一个SYN包(Sequence 1803591875)请求建链,第二个包是服务端对客户端的请求的确认,发送了ACK包(Sequence 1803591876),同时也给客户端发送了一个SYN包(Sequence 93871103),第三个包是客户端收到服务端的SYN+ACK包后,对服务端进行了回应,发送了ACK包(Sequence 93871104),至此客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成了三次握手。完成三次握手,客户端与服务器开始传送数据。
如果客户端发送SYN包之后,一直收不到服务端的ACK包,这时候就要排查下MySQL服务器以及中间网络是否正常了。
接下来我们再看下MySQL的断链过程。首先是客户端发送了FIN包(Sequence 1803593470),服务端收到后对客户端的请求进行确认,发送给客户端了一个ACK包(Sequence 1803593471),此时客户端只能接收数据而不能发送数据了。紧接着服务端向客户端发送了一个FIN包(Sequence 93871103),客户端收到FIN包后发ACK进行确认,至此四次挥手完成,链接关闭。
如果你的应用客户端有大量CLOSE_WAIT状态的链接,很有可能就是MySQL服务异常重启了。
案例二
在实际的运维过程中,有时业务反应慢,应用端也能看到SQL执行的时间比较长,但是数据库的慢日志中并没有抓到慢SQL。首先我们能想到的原因可能是SQL执行虽然慢但是还没有达到long_query_time定义的基线,或者是数据库执行很快,但是中间的网络出现了异常,亦或者就是数据库执行SQL的时间慢。这种问题该如何定位呢?这时候仅仅说数据库没有问题是没有说服力的,必须拿出真实数据来自证其说。这时候就可以通过tcpdump来定位问题了。
1. 在数据库上进行抓包
tcpdump -i eth0 -s0 port 3306 -w SlowSql.pcap
应用程序抓到了一个慢sql,慢sql的执行时间大约5.6秒,执行的sql为:select count(1) from table_test。执行完sql后停止抓包
2. 打开pcap包
3. 跟踪TCP流
搜索关键字table_test,找到一条记录,点击Follow TCP Stream,跟踪TCP流
4. 分析TCP流
我们详细分析下这几条TCP流
第一条记录:
这条记录是应用向MySQL服务器发出sql请求,发送时间是09:52:15.488165,右下角可以看到执行的sql:select count(1) from table_test。
第二条记录:
这条记录是数据库收到sql后,给客户端发送的确认ACK,表明已经收到了sql,发送的时间是09:52:15.530525。
第二条的时间减去第一条的时间为42.360ms。即MySQL服务器接收到应用的请求用了约42ms。
第三条记录:
第三条记录是数据库执行完sql把结果返回给应用,右下角可以看到查询结果是2439392。返回的时间是09:52:21.080593。第三条减去第二条的时间是5.55s,这就是数据库执行sql的时间。
第四条记录:
第四条记录是应用给数据库服务器发送了ACK(Sequence 2479403991),并发起了另一笔请求,这条记录表明应用已经收到数据库返回的查询结果了。
第四条发送时间是09:52:21.082586,减去第三条的时间为1.99ms,这个时间是数据库返回结果到应用收到的时间。
通过整个TCP流的分析跟踪,基本可以判断出整个sql执行过程中慢在了数据库端,耗时约5.6s,整个过程中也没有丢包重传,也没有其他耗时的的情况发生,说明网络是正常的。
通过以上两个案例可以看出tcpdump在DBA实际工作中的重要性,不仅能诊断网络丢包、网络延迟的问题,还能协助DBA进行一些复杂数据库问题的诊断。