只挑选几个重点命令讲解
1 COM_QUERY
COM_QUERY用于向服务器发送立即执行的基于文本的查询。
报文结构:
3 bytes 报文长度 | 1 byte 序号 | 1 byte 命令 | n bytes 参数 |
---|
包体部分:
- command_id ( 1 ):0x03 COM_QUERY
- query ( string.EOF ):query_text
查询字符串的长度取自数据包长度-1。
报文实例:
2 COM_QUERY响应
COM_QUERY响应报文可能是:
1. ERR_Packet报文
2. OK_Packet报文
3. Protocol::LOCAL_INFILE_Request (本文不介绍该报文)
4. ProtocolText::Resultset
2.1 何时返回OK_Packet和ERR_Packet报文
如果SQL是create、insert、update或者是delete,则返回的是对应的OK_Packet或者ERR_Packet报文。
2.1.1 create语句返回报文
sql语句:
CREATE TABLE test(
id int auto_increment primary key,
type_char char(10) DEFAULT NULL
);
create语句报文:
create语句响应报文:
语句执行成功,返回OK_Packet,蓝色部分为mysql协议报文,第5字节0x00表示OK_Packet,第6个字节表示影响行数。
2.1.2 insert语句返回报文
sql语句:
insert into test(type_char) values('test_value');
insert语句报文:
insert语句响应报文:
语句执行成功,返回OK_Packet,蓝色部分为mysql协议报文,第5字节0x00表示OK_Packet,第6个字节表示影响行数,第7个字节表示insert id。
2.1.3 update语句返回报文
sql语句:
update test set type_char='update' where id=1;
update语句报文:
update语句响应报文:
语句执行成功,返回OK_Packet,蓝色部分为mysql协议报文,第5字节0x00表示OK_Packet,第6个字节表示影响行数。
2.1.4 delete语句返回报文
sql语句:
delete from test where id=1;
delete语句报文:
delete语句响应报文:
语句执行成功,返回OK_Packet,蓝色部分为mysql协议报文,第5字节0x00表示OK_Packet,第6个字节表示影响行数。
2.1.5 ERR_Packet报文
当客户端删除一个不存在表的数据的时候,客户端后收到ERR_Packet报文。
delele from test_delete;
ERR_Packet报文:
2.2 resultSet结果集
column_count数据包: 第一个包包含一个Protocol::LengthEncodedInteger类型整数,表示列数
ColumnDefinition数据包:结果集列定义,有column_count个Protocol::ColumnDefinition数据包
EOF_Packet:如果CLIENT_DEPRECATE_EOF客户端能力标志未设置,那么是一个EOF_Packet数据包
ResultsetRow数据包:一个或多个ProtocolText::ResultsetRow数据包,每个包含column_count值
ERR_Packet/EOF_Packet/OK_Packet:发生错误是ERR_Packet数据包; 另外:如果设置了CLIENT_DEPRECATE_EOF客户端能力标志是OK_Packet数据包,否则是EOF_Packet数据包。
如果在最后一个EOF_Packet或者OK_Packet中设置了SERVER_MORE_RESULTS_EXISTS标志(如果设置了CLIENT_DEPRECATE_EOF能力标志就是OK_Packet), 将会跟随另一个ProtocolText::Resultset (请参阅多结果集)。
2.2 列数据类型
请参考:https://dev.mysql.com/doc/internals/en/com-query-response.html#text-resultset
2.3 列定义
lenenc_str catalog
lenenc_str schema
lenenc_str table
lenenc_str org_table
lenenc_str name
lenenc_str org_name
lenenc_int length of fixed-length fields [0c]
2 character set
4 column length
1 type
2 flags
1 decimals
2 filler [00] [00]
if command was COM_FIELD_LIST {
lenenc_int length of default-values
string[$len] default values
}
字段说明:
catalog (lenenc_str) :目录,值总是为def
schema (lenenc_str) : schema名称
table (lenenc_str) :虚拟表名
org_table (lenenc_str) :物理表名
name (lenenc_str) :虚拟列名
org_name (lenenc_str) :物理列名
next_length (lenenc_int): 以下字段的长度(始终为0x0c )
character_set (2) :是列字符集,并在Protocol::CharacterSet中定义
column_length (4):字段的最大长度
column_type (1):列类型中定义的列的类型
flags (2) :flags
decimals (1) :最大显示十进制数字
整数和静态字符串为0x00
动态字符串,double,float为0x1f
小数位为0x00至0x51
注意:decimals和column_length可用于文本输出格式。
2.4 文本结果集行
一个ProtocolText :: ResultsetRow包含一行与每列的数据。
NULL表示为0xfb。
一切都转换成一个字符串,并作为Protocol::LengthEncodedString发送。
2.5 实例
语句:
select 1
wireshark解析的报文:
wireshark捕获的二进制报文: