Tcpdump一次抓包记录(Postgresql通信)

Tcpdump一次抓包记录(Postgresql通信),第1张

概述数据库版本:postgresql 9.2.1 作者:高铭杰 邮箱:jackgo73@outlook.com 日期:2016年7月14日 1 背景   最近在调试一个gsql灌数据时的卡死问题,问题的跟因还没有分析清楚,和社区上的一个问题十分类似:    BUG #6342: libpq blocks forever in “poll” function Hi, I have a big and s

数据库版本:postgresql 9.2.1
作者:高铭杰
邮箱:jackgo73@outlook.com
日期:2016年7月14日

1 背景

  最近在调试一个gsql灌数据时的卡死问题,问题的跟因还没有分析清楚,和社区上的一个问题十分类似:
  

BUG #6342: libpq blocks forever in “poll” function
Hi,
I have a big and strange problem. Sometimes,libpq remains blocked in “poll”
function even if the server has already answered to the query. If I attach
to the process using kdbg I found this stack:

__kernel_vsyscall()
poll() from /lib/libc.so.6
pqSocketCheck() from /home/pg/pgsql/lib-32/libpq.so.5
pqWaitTimed() from /home/pg/pgsql/lib-32/libpq.so.5
pqWait() from /home/pg/pgsql/lib-32/libpq.so.5
PQgetResult() from /home/pg/pgsql/lib-32/libpq.so.5
PQexecFinish() from /home/pg/pgsql/lib-32/libpq.so.5

http://postgresql.nabble.com/BUG-6342-libpq-blocks-forever-in-quot-poll-quot-function-td5079577.html

为了分析清楚这类问题,这里记录一下使用tcpdump的方式去分析pg的通信过程。

2 Tcpdump安装

下载网址:http://www.tcpdump.org/#latest-release

- 下载tcpdump-4.6.2.tar.gz  libpcap-1.6.2.tar.gz - 编译安装libpcap - 编译安装tcpdump

sudo yum search tcpdumpsudo yum install tcpdump.xxx

ps. tcpdump提供了c接口:http://www.tcpdump.org/pcap.html

3 Tcpdump 参数
name       tcpdump - dump traffic on a networkSYnopSIS       tcpdump [ -AbdDefhHIJKlLnnopqRStuUvxX ] [ -B buffer_size ] [ -c count ] [ -C file_size ] [ -G rotate_seconds ] [ -F file ] [ -i interface ] [ -j tstamp_type ] [ -m module ] [ -M secret ] [ -P in|out|inout ] [ -r file ] [ -V file ] [ -s snaplen ] [ -T type ] [ -w file ] [ -W filecount ] [ -E spi@ipaddr algo:secret,...  ] [ -y datalinktype ] [ -z postrotate-command ] [ -Z user ] [ Expression ] 
4 使用Tcpdump调试Postgresql

连接数据库,注意使用gsql -h的方式,否则直接连接会创建进程通信用的本地socket,这样是无法使用Tcpdump抓包的:

连接数据库后,确认TCP连接已经建立,我的数据库port=8473:

现在就可以使用tcpdump进行抓包了:
sudo tcpdump tcp port 8473 -i lo -s0 -nnX
执行后,在数据库中执行sql:drop table TEST;

这里看到Tcpdump共抓到了3个TCP包,连接没有加密,所以部分指令以明文显示。

1、psql发送drop table TEST。23:44:08.563717 IP 127.0.0.1.53757 > 127.0.0.1.84732、数据库后端返回结果。23:44:08.570911 IP 127.0.0.1.8473 > 127.0.0.1.537573、psql向后端发包。23:44:08.570942 IP 127.0.0.1.53757 > 127.0.0.1.8473

(20160714以上)

5 分析数据(非连接池) 5.1 执行sql
select * from test;
5.2 抓包情况

抓到了三个包,这里只引出分析方法,不同的sql有不同的通信策略。、

方向:

内容:

5.2.1 第一个包[PSH,ACK][Q]

51开头的高亮部分是数据库填充的数据,前四行和第五行的60 94是IP和TCP报文。(TCP/IP报头分析的一篇博客)

  数据库填充的数据为:

|5100这里开始为数据库填充的数据       0x0030:  0002 6094 5100 0000 1873 656c 6563 7420  ..`.Q....select.    0x0040:  2a20 6672 6f6d 2074 6573 743b 00         *.from.test;.

  消息的第一个字节标识消息类型,然后后面跟着的四个字节声明消息剩下部分的长度(这个长度包括长度域自身,但是不包括消息类型字节)。请根据消息类型去手册中查询对应的包,这里第一个字节为Q决定了消息的格式:

query (F)    Byte1(’Q’)        标识消息是一个简单查询。    Int32        以字节计的消息内容长度,包括长度本身。    String        查询字符串自身
5.2.1 第二个包[PSH,ACK][T]

sql执行结果:

postgres=# select * from test; i --- 1(1 row)
Byte1(’T’)    标识消息是一个行描述    Int32        以字节计的消息内容长度,包括长度本身。    Int16        声明在一个行里面的字段数目(可以为零)    然后对于每个字段,有下面的东西:    String        字段名字    Int32        如果字段可以标识为一个特定表的字段,那么就是表的对象ID;否则就是零。    Int16        如果该字段可以标识为一个特定表的字段,那么就是该表字段的属性号;否则就是零。    Int32        字段数据类型的对象ID    Int16        数据类型尺寸(参阅pg_type.typlen)。请注意负数表示变宽类型。    Int32        类型修饰词(参阅pg_attribute.atttypmod)。修饰词的含义是类型相关的。    Int16        用于该字段的格式码。目前会是0(文本)或者1(二进制)。         从语句的Describe 返回的RowDescription里,格式码还是未知的,因此总是零。
5.2.1 第三个包[ACK]

ps. 抓包分析过程

1、sudo tcpdump -i lo -s0 -X port 8473 -w select.cap

生成select.cap

2、使用wireshark打开select.cap

总结

以上是内存溢出为你收集整理的Tcpdump一次抓包记录(Postgresql通信)全部内容,希望文章能够帮你解决Tcpdump一次抓包记录(Postgresql通信)所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/sjk/1174258.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-02
下一篇 2022-06-02

发表评论

登录后才能评论

评论列表(0条)

保存