6.4.1 监听连接

监听连接是 MySQL 服务的入口,其核心是 Connection_acceptor 模板类与 Mysqld_socket_listener 类协同工作的 connection_event_loop 事件循环。整个过程可分为初始化、循环监听与接受、分发处理三个阶段。

🚀 阶段一:网络初始化 (Network Initialization)

在 mysqld_main 函数完成一系列初始化后,会调用 network_init 来建立服务端的监听套接字(Socket)。

  1. 创建套接字 :
    • 根据配置,为 TCP/IP 协议(默认3306端口)创建套接字,会优先尝试 IPv4,若失败则尝试 IPv6。
    • 同时,也会为本地连接的 Unix Socket(类Unix系统)或 Windows Named Pipe 创建监听套接字。
  2. 绑定与监听 :
    • 将套接字绑定(bind)到指定的 IP 地址和端口。
    • 调用 listen 使套接字进入监听状态,等待客户端的连接请求。

如果 MySQL 异常退出后快速重启,可能出现端口被旧进程占用导致绑定失败的情况。此时 MySQL 会进入循环等待,直到端口被释放或超过 --port-open-timeout 设定的超时时间。

🔁 阶段二:事件循环与连接接受

完成初始化后,程序会进入由 Connection_acceptor 管理的核心事件循环 connection_event_loop,其核心任务是循环监听并接受新连接。

  • 事件循环机制:

    • 在循环中,会不断调用 Mysqld_socket_listener 对象的 listen_for_connection_event 方法。
    • 该方法底层使用 poll 或 select 系统调用来监听套接字上的 I/O 事件。MySQL 选择 poll/select 而非 epoll,主要是为了跨平台的可移植性。
  • 接受新连接:

    • 当 poll/select 检测到监听套接字上有新连接到达时,listen_for_connection_event 会调用 mysql_socket_accept 接受连接。
    • 成功接受后,会创建一个 Channel_info 对象,它像一个"数据包",封装了本次连接的所有信息,如客户端的 socket 文件描述符、IP 和端口等。

⚙️ 阶段三:连接处理与分发

获取到封装了连接信息的 Channel_info 对象后,核心处理流程转向 Connection_handler_manager 类。

  1. 连接数检查 :Connection_handler_manager 会调用 check_and_incr_conn_count 检查当前连接数。若已达到 max_connections 限制,新连接会被拒绝(但会为 root 用户预留一个额外的连接通道用于紧急管理)。

  2. 分发与创建线程 :连接数检查通过后,管理器会调用 add_connection 方法。这一步会分发到具体的 Connection_handler 实现。

    • 默认的 Per_thread_connection_handler 会为每个新连接创建一个线程。为了优化性能,会优先尝试从 thread_cache 中复用空闲线程。
    • 新线程(无论是新建还是复用)的入口函数是 handle_one_connection(或 handle_connection)。这个线程随后会负责该连接整个生命周期的所有操作。

    值得一提的是,MySQL 5.7 对此流程进行了优化,将 THD(线程描述符)、NET、VIO 等会话对象的初始化工作交给了新创建的用户线程自身去完成,使得主线程能更专注于高效接受新连接。

🤝 连接线程的后续任务

新线程启动后,会执行一系列初始化,并与客户端完成握手认证:

  • 初始化会话与网络对象 :线程入口函数会初始化 THD(线程描述符)、VIO(虚拟I/O)和 NET 等关键对象。其中 VIO 是对底层 Socket 的抽象,提供了 vio_read 和 vio_write 等回调函数。同时,连接 socket 会被设置为非阻塞模式 (O_NONBLOCK)。
  • 握手与认证 :
    1. 发送握手包 :服务端向客户端发送一个包含挑战码(scramble) 的握手初始化包。
    2. 客户端响应:客户端使用挑战码加密密码,将加密后的密码连同用户名等信息打包发回服务端。
    3. 服务端验证:服务端解密并验证密码,检查用户账户和权限。
    4. 返回结果 :验证通过则返回 OK 包,连接成功建立;否则返回 ERROR 包。
  • 进入命令循环 :认证通过后,线程便进入 do_command 循环,持续读取、解析并执行客户端发来的 SQL 命令。

💎 总结

MySQL 的监听连接机制,是一套经过精心设计的、清晰优雅的事件驱动模型。其核心流程可以概括为:

  1. 准备 :mysqld_main 启动后,通过 network_init 创建并配置好监听套接字。
  2. 循环 :进入 connection_event_loop,主线程通过 poll/select 高效地等待新连接。
  3. 接受 :当新连接到达,主线程将其接受,并封装为 Channel_info 对象。
  4. 分发 :Connection_handler_manager 检查连接数限制后,将连接分发出去。
  5. 处理:通常由独立的线程接管连接,完成握手认证,最后进入 SQL 命令的处理循环。

这一系列流程,共同构成了 MySQL 能够处理成千上万并发连接的基础。

java 复制代码
/**
 连接接受器循环以接受来⾃客户端的连接
    Connection acceptor loop to accept connections from clients.
  */
  void connection_event_loop() {
    Connection_handler_manager *mgr =
        Connection_handler_manager::get_instance();
    while (!connection_events_loop_aborted()) {
      // 监听连接事件
      Channel_info *channel_info = m_listener-
>listen_for_connection_event();
      // 处理⼀个新的连接
      if (channel_info != nullptr) mgr-
>process_new_connection(channel_info);
   }
相关推荐
PaperData8 小时前
1985-2025年全国区县专利申请与授权面板数据
数据库
snpgroupcn8 小时前
大数据量SAP迁移方案:系统越大,越不能硬搬
数据库·sap
leikooo8 小时前
用餐厅和盘子理解栈和堆
java·数据结构·链表·rust
Flynt9 小时前
Redis Cluster主节点挂了,为什么"高可用"还全员掉线?我把三次kill的记录翻出来了
数据库·redis·分布式
笃行3509 小时前
KingbaseES 数据加密全解:从 SSL 到全密态
数据库
Ivanqhz9 小时前
激活函数在 Transformer 中的作用及各种变体简述
java·linux·数据库·人工智能·深度学习
沙漠之主9 小时前
C++编程教学设计资料:从入门到实战的完整课程方案
java·前端·c++
FPGA小徐10 小时前
PA1 基础设施(2)深度解析:NEMU 中 ITRACE、MTRACE、FTRACE、IRINGBUF、ETRACE、DIFFTEST 全解析
java·服务器·网络
YOLO数据集集合10 小时前
EvoAgent:面向PR研发治理的自进化Multi-Agent Harness系统
java·开发语言·目标检测·agent·自进化
java1234_小锋10 小时前
【技术专题】Mysql8 数据库 - Mysql8 数据类型简介
数据库·mysql