mysql8 从C++源码角度看 客户端发送的sql信息 mysql服务端从网络读取到buff缓存中

MySQL 8 版本中的客户端-服务器通信相关,特别是在接收和解析网络请求的数据包时。以下是对代码各个部分的详细解释,帮助您更好地理解这些代码的作用。

代码概述

这段代码主要负责从网络读取数据包,它包含了多个函数来处理网络数据的读取、缓冲区管理、包的解压缩、重试机制和超时处理等。

核心部分概述
  1. net_read_packet 函数: 该函数是 MySQL 网络协议栈的一个核心函数,用于从网络上读取一个数据包。它处理了数据包头的读取、压缩包的处理、包的重新分配和数据的实际读取。其工作流程是:

    • 读取包头,获取包的长度。
    • 如果包是压缩的,则解压缩并更新 complen(解压后的包长度)。
    • 检查是否需要扩展缓冲区来适应包的内容。
    • 最终调用 net_read_raw_loop 读取实际的包数据。
  2. net_read_raw_loop 函数: 这个函数是读取原始数据的实际工作函数,它通过 vio_read 函数从套接字中读取指定数量的字节。如果读取过程中遇到错误,会进行重试;如果读取到 EOF 或者发生超时,它会处理这些情况并返回相应的错误。

  3. net_read_uncompressed_packet 函数: 该函数处理未压缩的数据包,读取数据包并检查是否是一个大数据包的开始。如果数据包是一个多包数据的开始(通过 0xFFFFFF 标识),则会继续读取后续的包并将它们连接在一起。

  4. my_net_read 函数: 这是一个统一的入口函数,用于读取数据包。根据网络连接的压缩标志,它会选择读取压缩或未压缩的包。如果是压缩包,它会调用 net_read_compressed_packet,否则调用 net_read_uncompressed_packet

  5. Protocol_classic::read_packet 函数: 这个函数属于 MySQL 8 协议类 Protocol_classic 的一部分。它调用 my_net_read 来读取数据包并检查数据包的有效性。如果数据包的长度无效(packet_error),则标记该包为错误包。否则,它将数据包存储在 input_raw_packet 中,并返回成功。

  6. Protocol_classic::get_command 函数: 这个函数解析并处理客户端发送的命令数据包。它首先调用 read_packet 函数读取数据包,然后从数据包的第一个字节中提取命令类型(如 COM_SLEEP 等),并将其存储到 cmd 变量中。接着,它会跳过命令字节,并解析剩余的数据。

数据包读取过程

  • 数据包头读取net_read_packet 首先通过 net_read_packet_header 函数读取数据包的头部信息(包括数据包的长度)。如果数据包头部的读取失败,它会返回错误。

  • 压缩数据包的处理:如果数据包是压缩的(net->compress 为真),则会通过 net_read_compressed_packet 解压缩数据包并更新 complen(解压后的数据包长度)。压缩包的具体处理逻辑是通过解析压缩包的头部和数据内容来完成的。

  • 多包处理:如果数据包的长度为最大值(MAX_PACKET_LENGTH),则表示这是一个多包数据的第一部分,需要继续读取后续的包并将它们拼接在一起。这个过程在 net_read_uncompressed_packet 函数中进行。

  • 错误处理和超时机制:如果在读取过程中发生错误,net_read_raw_loop 会处理多种情况,如重试、EOF 或超时。错误信息通过 net->last_errno 进行记录,客户端会根据这个信息做相应的处理。特别地,超时会触发不同的错误,如 ER_NET_READ_INTERRUPTEDER_CLIENT_INTERACTION_TIMEOUT

关键函数总结

  • net_read_packet:负责读取一个完整的网络数据包,处理压缩和扩展缓冲区的逻辑。
  • net_read_raw_loop:核心的循环读取函数,负责从网络读取数据,并处理错误和超时。
  • my_net_read:统一的接口函数,调用 net_read_compressed_packetnet_read_uncompressed_packet 来读取数据包。
  • Protocol_classic::read_packetProtocol_classic::get_command:这两个函数属于 MySQL 协议类,负责接收客户端请求并解析相应的命令。

结论

这些代码主要用于处理 MySQL 8 客户端和服务器之间的网络通信,特别是处理数据包的读取、解压、分片拼接以及错误处理。它们确保能够从客户端接收到数据包并将其解析为 MySQL 服务器理解的格式。这些代码对于处理客户端请求、执行 SQL 命令和返回结果至关重要。

##源码

static size_t net_read_packet(NET *net, size_t *complen) {size_t pkt_len, pkt_data_len;*complen = 0;net->reading_or_writing = 1;/*We should reset compress_packet_nr even before reading the header becausereading can fail and then the compressed packet number won't get reset.*/net->compress_pkt_nr = net->pkt_nr;/* Retrieve packet length and number. */if (net_read_packet_header(net)) goto error;net->compress_pkt_nr = net->pkt_nr;if (net->compress) {/*The right-hand expressionmust match the size of the buffer allocated in net_realloc().*/assert(net->where_b + NET_HEADER_SIZE + 3 <=net->max_packet + NET_HEADER_SIZE + COMP_HEADER_SIZE);/*If the packet is compressed then complen > 0 and contains thenumber of bytes in the uncompressed packet.*/*complen = uint3korr(&(net->buff[net->where_b + NET_HEADER_SIZE]));}/* The length of the packet that follows. */pkt_len = uint3korr(net->buff + net->where_b);/* End of big multi-packet. */if (!pkt_len) goto end;pkt_data_len = max(pkt_len, *complen) + net->where_b;/* Expand packet buffer if necessary. */if ((pkt_data_len >= net->max_packet) && net_realloc(net, pkt_data_len))goto error;/* Read the packet data (payload). */if (net_read_raw_loop(net, pkt_len)) goto error;end:if (net->error == NET_ERROR_SOCKET_NOT_WRITABLE)net->error = NET_ERROR_SOCKET_UNUSABLE;DBUG_DUMP("net read", net->buff + net->where_b, pkt_len);net->reading_or_writing = 0;return pkt_len;error:if (net->error == NET_ERROR_SOCKET_NOT_WRITABLE)net->error = NET_ERROR_SOCKET_UNUSABLE;net->reading_or_writing = 0;return packet_error;
}/*****************************************************************************
** Read something from server/clinet
*****************************************************************************//**Read a determined number of bytes from a network handler.@param  net     NET handler.@param  count   The number of bytes to read.@return true on error, false on success.
*/static bool net_read_raw_loop(NET *net, size_t count) {DBUG_TRACE;bool eof = false;unsigned int retry_count = 0;uchar *buf = net->buff + net->where_b;bool timeout_on_full_packet = false;bool is_packet_timeout = false;
#ifdef MYSQL_SERVERNET_SERVER *server_ext = static_cast<NET_SERVER *>(net->extension);if (server_ext) timeout_on_full_packet = server_ext->timeout_on_full_packet;
#endiftime_t start_time = 0;if (timeout_on_full_packet) start_time = time(&start_time);while (count) {const size_t recvcnt = vio_read(net->vio, buf, count);/* VIO_SOCKET_ERROR (-1) indicates an error. */if (recvcnt == VIO_SOCKET_ERROR) {/* A recoverable I/O error occurred? */if (net_should_retry(net, &retry_count))continue;elsebreak;}/* Zero indicates end of file. */else if (!recvcnt) {eof = true;break;}count -= recvcnt;buf += recvcnt;
#ifdef MYSQL_SERVERthd_increment_bytes_received(recvcnt);
#endifif (timeout_on_full_packet) {time_t current_time = time(&current_time);if (static_cast<unsigned int>(current_time - start_time) >net->read_timeout) {is_packet_timeout = true;break;}}}/* On failure, propagate the error code. */if (count) {/* Interrupted by a timeout? */if (!eof && (vio_was_timeout(net->vio) || is_packet_timeout))net->last_errno = ER_NET_READ_INTERRUPTED;elsenet->last_errno = ER_NET_READ_ERROR;#ifdef MYSQL_SERVER/* First packet always wait for net_wait_timeout */if (net->pkt_nr == 0 && (vio_was_timeout(net->vio) || is_packet_timeout)) {net->last_errno = ER_CLIENT_INTERACTION_TIMEOUT;/* Socket should be closed after trying to write/send error. */THD *thd = current_thd;if (thd) {Security_context *sctx = thd->security_context();std::string timeout{std::to_string(thd_get_net_wait_timeout(thd))};Auth_id auth_id(sctx->priv_user(), sctx->priv_host());LogErr(INFORMATION_LEVEL, ER_NET_WAIT_ERROR2, timeout.c_str(),auth_id.auth_str().c_str());} else {LogErr(INFORMATION_LEVEL, ER_NET_WAIT_ERROR);}}net->error = NET_ERROR_SOCKET_NOT_READABLE;/*Attempt to send error message to client although the client won't beexpecting messages. If later the client tries to send a command and failit will instead check if it can read an error message.*/my_error(net->last_errno, MYF(0));
#else/* Socket should be closed. */net->error = NET_ERROR_SOCKET_UNUSABLE;
#endif}return count != 0;
}/**Reads one packet to net->buff + net->where_b.If the packet is the first packet of a multi-packet packet(which is indicated by the length of the packet = 0xffffff) thenall sub packets are read and concatenated.@param[in, out] net NET structure@param[out] len  length of the packet read
*/
static void net_read_uncompressed_packet(NET *net, size_t &len) {size_t complen;assert(!net->compress);len = net_read_packet(net, &complen);if (len == MAX_PACKET_LENGTH) {/* First packet of a multi-packet.  Concatenate the packets */const ulong save_pos = net->where_b;size_t total_length = 0;do {net->where_b += len;total_length += len;len = net_read_packet(net, &complen);} while (len == MAX_PACKET_LENGTH);if (len != packet_error) len += total_length;net->where_b = save_pos;}net->read_pos = net->buff + net->where_b;if (len != packet_error)net->read_pos[len] = 0; /* Safeguard for mysql_use_result */
}/**Read a packet from the client/server and return it without the internalpackage header.If the packet is the first packet of a multi-packet packet(which is indicated by the length of the packet = 0xffffff) thenall sub packets are read and concatenated.If the packet was compressed, its uncompressed and the length of theuncompressed packet is returned.@returnThe function returns the length of the found packet or packet_error.net->read_pos points to the read data.
*/ulong my_net_read(NET *net) {size_t len;/* turn off non blocking operations */if (!vio_is_blocking(net->vio)) vio_set_blocking_flag(net->vio, true);if (net->compress)net_read_compressed_packet(net, len);elsenet_read_uncompressed_packet(net, len);return static_cast<ulong>(len);
}int Protocol_classic::read_packet() {input_packet_length = my_net_read(&m_thd->net);if (input_packet_length != packet_error) {assert(!m_thd->net.error);bad_packet = false;input_raw_packet = m_thd->net.read_pos;return 0;}bad_packet = true;return m_thd->net.error == NET_ERROR_SOCKET_UNUSABLE ? 1 : -1;
}int Protocol_classic::get_command(COM_DATA *com_data,enum_server_command *cmd) {// read packet from the networkif (const int rc = read_packet()) return rc;/*'input_packet_length' contains length of data, as it was stored in packetheader. In case of malformed header, my_net_read returns zero.If input_packet_length is not zero, my_net_read ensures that the returnednumber of bytes was actually read from network.There is also an extra safety measure in my_net_read:it sets packet[input_packet_length]= 0, but only for non-zero packets.*/if (input_packet_length == 0) /* safety */{/* Initialize with COM_SLEEP packet */input_raw_packet[0] = (uchar)COM_SLEEP;input_packet_length = 1;}/* Do not rely on my_net_read, extra safety against programming errors. */input_raw_packet[input_packet_length] = '\0'; /* safety */*cmd = (enum enum_server_command)(uchar)input_raw_packet[0];if (*cmd >= COM_END) *cmd = COM_END;  // Wrong commandassert(input_packet_length);// Skip 'command'input_packet_length--;input_raw_packet++;return parse_packet(com_data, *cmd);
}

##gdb调试栈

(gdb) bt
#0  net_read_packet (net=0x7fd000002bb8, complen=0x7fd0e48fc250) at /home/yym/mysql8/mysql-8.1.0/sql-common/net_serv.cc:2125
#1  0x00005d830c9eb995 in net_read_uncompressed_packet (net=0x7fd000002bb8, len=@0x7fd0e48fc290: 140535164556864) at /home/yym/mysql8/mysql-8.1.0/sql-common/net_serv.cc:2165
#2  0x00005d830c9ebccc in my_net_read (net=0x7fd000002bb8) at /home/yym/mysql8/mysql-8.1.0/sql-common/net_serv.cc:2241
#3  0x00005d830cf1cd2a in Protocol_classic::read_packet (this=0x7fd0000052e0) at /home/yym/mysql8/mysql-8.1.0/sql/protocol_classic.cc:1411
#4  0x00005d830cf1e08f in Protocol_classic::get_command (this=0x7fd0000052e0, com_data=0x7fd0e48fc340, cmd=0x7fd0e48fc330)at /home/yym/mysql8/mysql-8.1.0/sql/protocol_classic.cc:2995
#5  0x00005d830c7c0b5a in do_command (thd=0x7fd000000d80) at /home/yym/mysql8/mysql-8.1.0/sql/sql_parse.cc:1397
#6  0x00005d830ca18835 in handle_connection (arg=0x5d83166b17d0) at /home/yym/mysql8/mysql-8.1.0/sql/conn_handler/connection_handler_per_thread.cc:303
#7  0x00005d830e957bdc in pfs_spawn_thread (arg=0x5d83166ae7e0) at /home/yym/mysql8/mysql-8.1.0/storage/perfschema/pfs.cc:3043
#8  0x00007fd0f3894ac3 in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:442
#9  0x00007fd0f3926850 in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81
(gdb) p net->buff
$10 = (unsigned char *) 0x7fd0000076f0 "\003KILL QUERY 8"

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/498624.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

结合长短期记忆网络(LSTM)和无迹卡尔曼滤波器(UKF)的技术在机器人导航和状态估计中的应用前景

结合长短期记忆网络(LSTM)和无迹卡尔曼滤波器(UKF)的技术在机器人导航和状态估计中具有广泛的应用前景。如有滤波、导航方面的代码定制需求,可通过文末卡片联系作者获得帮助 文章目录 结合LSTM和UKF的背景结合LSTM和UKF的优势应用实例研究现状MATLAB代码示例结论结合LSTM和…

Spring源码下载与测试

引言 下载了Spring源码想阅读阅读&#xff0c;发现用的是Gradle&#xff0c;原来实习的时候公司用的也是Gradle&#xff0c;但不怎么会用&#xff0c;感觉相比于Maven&#xff0c;Gradle更适合非常大型的项目&#xff0c;因为他的jar包下载的是真快 下载 由于Spring6开始就强…

【HarmonyOS之旅】ArkTS语法(三) -> 渲染控制

目录 1 -> 条件渲染 2 -> 循环渲染 3 -> 数据懒加载 3.1 -> IDataSource类型说明 3.2 -> DataChangeListener类型说明 ArkTS也提供了渲染控制的能力。条件渲染可根据应用的不同状态&#xff0c;渲染对应状态下的UI内容。循环渲染可从数据源中迭代获取数据&…

再见2024,你好2025

再见2024&#xff0c;你好2025 1月2月3月4月5~10月11~12月一些收获读书跑步工作 为了让这篇博客不那么平淡&#xff0c;一句话可以总结为&#xff1a;平平无奇的琐碎&#xff0c;没有亮点成果。 也可以数字化概述&#xff1a;涨了1万粉&#xff0c;赚了10万&#xff0c;跑步300…

阴阳师の新手如何速刷5个SP/SSR?!(急速育成)

目标&#xff1a;攒5个SP/SSR式神&#xff0c;参与急速育成&#xff0c;省四个黑蛋&#xff08;想要快速升级技能而且经常上场的式神在攒够5个式神前先不升级&#xff09;【理论上组成&#xff1a;10蓝40蓝预约召唤福利20修行or抽卡】 关键点&#xff1a;蓝票&#xff0c;新手…

Kerberos用户认证-数据安全-简单了解-230403

hadoop安全模式官方文档&#xff1a;https://hadoop.apache.org/docs/r2.7.2/hadoop-project-dist/hadoop-common/SecureMode.html kerberos是什么 kerberos是计算机网络认证协议&#xff0c;用来在非安全网络中&#xff0c;对个人通信以安全的手段进行身份认证。 概念&#…

第 29 章 - ES 源码篇 - 网络 IO 模型及其实现概述

前言 本文介绍了 ES 使用的网络模型&#xff0c;并介绍 transport&#xff0c;http 接收、响应请求的代码入口。 网络 IO 模型 Node 在初始化的时候&#xff0c;会创建网络模块。网络模块会加载 Netty4Plugin plugin。 而后由 Netty4Plugin 创建对应的 transports&#xff0…

SQL 基础教程 - SQL SELECT 语句

SQL SELECT DISTINCT 语句 SELECT DISTINCT 语句用于返回唯一不同的值。 在表中&#xff0c;一个列可能会包含多个重复值&#xff0c;有时您也许希望仅仅列出不同&#xff08;distinct&#xff09;的值。 DISTINCT 关键词用于返回唯一不同的值。 SQL SELECT DISTINCT 语法 …

计算机网络基础知识(7)中科大郑铨老师笔记

协议层次及服务模型 计算机网络的分层设计方法&#xff0c;将复杂的网络功能分解为多个层次&#xff0c;每一层实现特定的功能。 互联网中的TCP/IP协议族&#xff0c;包括物理层、链 路层、网络层、传输层和应用层的功能。然后&#xff0c;数据传输的 过程&#xff0c;从应用层…

Microsoft word@【标题样式】应用不生效(主要表现为在导航窗格不显示)

背景 随笔。Microsoft word 2013基础使用&#xff0c;仅做参考和积累。 问题 Microsoft word 2013&#xff0c;对段落标题文字应用【标题样式】不生效&#xff08;主要表现为在导航窗格不显示&#xff09;。 图1 图2 观察图1和图2&#xff0c;发现图1的文字在应用【标题一】样…

TP 钱包插件版本的使用

目前 TokenPocket 的几个平台中&#xff0c;以 ios 和 安卓版本最为常见&#xff0c;其实很少有人知道&#xff0c;浏览器上有一个插件版本的 Tp, 用电脑多的话&#xff0c;这也是一个挺好的选择。 最新版本现在支持Chrome、Brave 浏览器、Edge&#xff08;Firefox及Opera正在…

微信流量主挑战:三天25用户!功能未完善?(新纪元4)

&#x1f389;【小程序上线第三天&#xff01;突破25用户大关&#xff01;】&#x1f389; 嘿&#xff0c;大家好&#xff01;今天是我们小程序上线的第三天&#xff0c;我们的用户量已经突破了25个&#xff01;昨天还是16个&#xff0c;今天一觉醒来竟然有25个&#xff01;这涨…

【AndroidAPP】权限被拒绝:[android.permission.READ_EXTERNAL_STORAGE],USB设备访问权限系统报错

一、问题原因 1.安卓安全性变更 Android 12 的安全性变更&#xff0c;Google 引入了更严格的 PendingIntent 安全管理&#xff0c;强制要求开发者明确指定 PendingIntent 的可变性&#xff08;Mutable&#xff09;或不可变性&#xff08;Immutable&#xff09;。 但是&#xf…

打印进度条

文章目录 1.Python语言实现(1)黑白色(2)彩色&#xff1a;蓝色 2.C语言实现(1)黑白颜色(2)彩色版&#xff1a;红绿色 1.Python语言实现 (1)黑白色 import sys import timedef progress_bar(percentage, width50):"""打印进度条:param percentage: 当前进度百分比…

ubuntu 使用samba与windows共享文件[注意权限配置]

在Ubuntu上使用Samba服务与Windows系统共享文件&#xff0c;需要正确配置Samba服务以及相应的权限。以下是详细的步骤&#xff1a; 安装Samba 首先&#xff0c;确保你的Ubuntu系统上安装了Samba服务。 sudo apt update sudo apt install samba配置Samba 安装完成后&#xff0c…

数据结构(哈希表)

背景 在对数据的日常处理中&#xff0c;查找是一项基本操作。通常&#xff0c;查找算法都是基于对比的&#xff0c;比如在一条链表中有n个节点&#xff0c;要找到其中的某个节点&#xff0c;最基本的思路就是从头到尾依次遍历每个节点&#xff0c;依次对比每个节点是否是想要的…

【每日学点鸿蒙知识】模拟器开启网络、长时任务、兼容性测试支持、丢帧定位、SO中访问rawfile等

1、模拟器如何开启网络&#xff1f; 模拟器使用的是电脑本身的网络&#xff0c;不通过代理即可访问网络。 2、创建子window后&#xff0c;锁屏很短时间内&#xff0c;应用会被杀死&#xff1f; 没开长时任务&#xff0c;锁屏和退后台保活要开长时任务。 应用退至后台后&…

如何解决Eigen和CUDA版本不匹配引起的错误math_functions.hpp: No such file or directory

Apollo9针对RTX40的docker环境里的Eigen库版本是3.3.4&#xff0c;CUDA是11.8: 编译我们自己封装模型的某些component代码时没问题&#xff0c;编译一个封装occ模型的component代码时始终报错: In file included from /usr/include/eigen3/Eigen/Geometry:11:0, …

Mac连接云服务器工具推荐

文章目录 前言步骤1. 下载2. 安装3. 常用插件安装4. 连接ssh测试5. 连接sftp测试注意&#xff1a;ssh和sftp的区别注意&#xff1a;不同文件传输的区别解决SSL自动退出 前言 Royal TSX是什么&#xff1a; Royal TSX 是一款跨平台的远程桌面和连接管理工具&#xff0c;专为 mac…

python修改ppt中的文字部分及插入图片

批量修改ppt中的某个模块&#xff0c;或者批量制作奖状等场景会用到&#xff1b; import os import pandas as pd from pptx import Presentation from pptx.util import Inchesfilepath/Users/kangyongqing/Documents/kangyq/202303/分析模版/批量制作/file1时段预警_副本.pp…