MySQL接收到SQL后的入口函数是do_command(),它位于sql/sql_parse.cc,负责初始化语句上下文、读取完整packet、识别命令类型并派发处理。
MySQL 接收到 SQL 后先走哪个入口函数?
MySQL 服务端接收到客户端发来的 SQL 字符串后,第一步不是解析,也不是优化,而是进入网络层的事件分发循环,最终调用 do_command() —— 这是 SQL 执行链路的真正入口函数(在经典线程模型下)。它位于 sql/sql_parse.cc,负责初始化语句上下文、读取完整 packet、识别命令类型(如 COM_QUERY),并派发到对应处理函数(比如 dispatch_command())。
注意:如果你用的是线程池(thread pool)或 X Protocol(mysqlx),入口会不同:handle_connection() 或 mysqlx::Connection::execute_statement(),但传统连接下 do_command() 是绕不开的第一站。
为什么不是直接 parse_sql()?
因为 MySQL 在真正解析前必须完成几件关键前置事:
-
do_command()要先检查连接状态、用户权限、字符集设置、事务状态(是否在 autocommit 模式) - 要从 socket 缓冲区中完整读取一个
COM_QUERY包(含长度头 + SQL 字符串),避免粘包或截断 - 要为这条语句分配临时
THD(Thread Handler)对象,并绑定当前线程与会话上下文 - 只有这些就绪后,才会调用
dispatch_command()→mysql_parse()→parse_sql()进入语法解析阶段
所以看到报错 ERROR 1045 (28000): Access denied 或 ERROR 1118 (42000): Row size too large,它们都发生在 mysql_parse() 之前 —— 说明连入口都没进完。
如何验证这个入口流程?
最轻量的方式是加 GDB 断点: