php一步一步实现mysql协议(四)——执行命令
执行命令消息
发送完认证请求之后,服务端返回 OK Response ,然后就可以发送执行命令消息了;报文结构为
例如
其中前四位属于消息头,包含消息体的长度和消息id,消息体部分包括 命令id和执行参数。这里命令id=3表示该命令是 SQL查询请求,后面跟着的是具体执行命令 “select * from users”。命令id代表的含义如下:
类型值 | 命令 | 功能 | 关联函数 |
---|---|---|---|
0x00 | COM_SLEEP | (内部线程状态) | (无) |
0x01 | COM_QUIT | 关闭连接 | mysql_close |
0x02 | COM_INIT_DB | 切换数据库 | mysql_select_db |
0x03 | COM_QUERY | SQL查询请求 | mysql_real_query |
0x04 | COM_FIELD_LIST | 获取数据表字段信息 | mysql_list_fields |
0x05 | COM_CREATE_DB | 创建数据库 | mysql_create_db |
0x06 | COM_DROP_DB | 删除数据库 | mysql_drop_db |
0x07 | COM_REFRESH | 清除缓存 | mysql_refresh |
0x08 | COM_SHUTDOWN | 停止服务器 | mysql_shutdown |
0x09 | COM_STATISTICS | 获取服务器统计信息 | mysql_stat |
0x0A | COM_PROCESS_INFO | 获取当前连接的列表 | mysql_list_processes |
0x0B | COM_CONNECT | (内部线程状态) | (无) |
0x0C | COM_PROCESS_KILL | 中断某个连接 | mysql_kill |
0x0D | COM_DEBUG | 保存服务器调试信息 | mysql_dump_debug_info |
0x0E | COM_PING | 测试连通性 | mysql_ping |
0x0F | COM_TIME | (内部线程状态) | (无) |
0x10 | COM_DELAYED_INSERT | (内部线程状态) | (无) |
0x11 | COM_CHANGE_USER | 重新登陆(不断连接) | mysql_change_user |
0x12 | COM_BINLOG_DUMP | 获取二进制日志信息 | (无) |
0x13 | COM_TABLE_DUMP | 获取数据表结构信息 | (无) |
0x14 | COM_CONNECT_OUT | (内部线程状态) | (无) |
0x15 | COM_REGISTER_SLAVE | 从服务器向主服务器进行注册 | (无) |
0x16 | COM_STMT_PREPARE | 预处理SQL语句 | mysql_stmt_prepare |
0x17 | COM_STMT_EXECUTE | 执行预处理语句 | mysql_stmt_execute |
0x18 | COM_STMT_SEND_LONG_DATA | 发送BLOB类型的数据 | mysql_stmt_send_long_data |
0x19 | COM_STMT_CLOSE | 销毁预处理语句 | mysql_stmt_close |
0x1A | COM_STMT_RESET | 清除预处理语句参数缓存 | mysql_stmt_reset |
0x1B | COM_SET_OPTION | 设置语句选项 | mysql_set_server_option |
0x1C | COM_STMT_FETCH | 获取预处理语句的执行结果 | mysql_stmt_fetch |
当客户端发送查询请求后,在没有错误的情况下,服务器会返回结果集(Result Set)给客户端。
Result Set 消息分为五部分,结构如下:
结构 | 说明 |
---|---|
[Result Set Header] | 列数量 |
[Field] | 列信息(多个) |
[EOF] | 列结束 |
[Row Data] | 行数据(多个) |
[EOF] | 数据结束 |
Result Set Header 结构
字节 | 说明 |
---|---|
1-9 | Field结构计数(Length Coded Binary) |
1-9 | 额外信息(Length Coded Binary) |
示例:
Result Set Field 结构
字节 | 说明 |
---|---|
n | 目录名称(Length Coded String) |
n | 数据库名称(Length Coded String) |
n | 数据表名称(Length Coded String) |
n | 数据表原始名称(Length Coded String) |
n | 列(字段)名称(Length Coded String) |
4 | 列(字段)原始名称(Length Coded String) |
1 | 填充值 |
2 | 字符编码 |
4 | 列(字段)长度 |
1 | 列(字段)类型 |
2 | 列(字段)标志 |
1 | 整型值精度 |
2 | 填充值(0x00) |
n | 默认值(Length Coded String) |
示例:
Result Row Data 结构:
字节 | 说明 |
---|---|
n | 字段值(Length Coded String) |
... | (一行数据中包含多个字段值) |
示例:
header结构体和field结构体报文中由于每个参数的字段都含有固定的位数,所以获取数据的时候只要按照固定位数截取数据就可以获取到响应参数数值。但是 row data 结构体的数据并没有固定的位数所以获取方式与上面两种不同,其应该先获取消息体重的首位字节数据并将其转为整数,该字节后面的长度数据即为实际数据值。例如:
01 31 04 6c 69 73 61
应该分成两部分 01 31 和 04 6c 69 73 61 分别表示 “1” 和 “lisa” 两个字符
代码分享地址
https://github.com/gphper/PHPMysql
参考文档:
https://dev.mysql.com/doc/internals/en/client-server-protocol.html
https://www.cnblogs.com/davygeek/p/5647175.html