MySQL调试核心是让SQL执行“看得见、停得住、改得动”,需开启general_log查全语句、slow_query_log定位慢查询、强制TCP连接确保网络层可控,并慎用init_connect注入上下文。

MySQL 调试环境不是装个客户端就行,核心是让 SQL 执行过程“看得见、停得住、改得动”。重点不在安装,而在开启日志、连接可控、语句可复现。
启用 general_log 查看每条执行语句
这是排查“SQL 没走预期逻辑”最直接的手段。它记录所有到达 MySQL 服务端的语句(含连接、断开),但默认关闭,且开启后有明显性能损耗,仅限本地调试或低流量环境。
-
general_log必须设为ON,且general_log_file指向可写的路径(如/tmp/mysql-general.log) - 动态开启命令:
SET GLOBAL general_log = ON; SET GLOBAL general_log_file = '/tmp/mysql-general.log';
- 注意:重启 MySQL 后失效,如需持久化,需在
my.cnf的[mysqld]段添加:general_log = ON general_log_file = /tmp/mysql-general.log
- 日志里会混入连接/断开信息,用
SELECT、UPDATE等关键字过滤更高效
用 slow_query_log 定位执行慢的语句
当用户反馈“页面卡”,但不知道哪条 SQL 慢时,这个日志比猜更有用。它不记录所有语句,只记录超过 long_query_time(默认 10 秒)的查询,可调低到 0.1 秒用于调试。
- 开启方式:
SET GLOBAL slow_query_log = ON; SET GLOBAL long_query_time = 0.1; SET GLOBAL slow_query_log_file = '/tmp/mysql-slow.log';
- 关键点:
log_queries_not_using_indexes设为ON可暴露缺失索引的查询,但会产生大量日志,调试初期建议先关着 - 注意:该日志不记录参数化查询中的实际值(如
WHERE id = ?),只记问号,所以需配合应用层日志或general_log看真实参数
连接调试环境必须用 --protocol=tcp
本地开发常直连 localhost,但 MySQL 默认会走 socket 文件(/tmp/mysql.sock),导致你配的 port、bind-address、甚至某些网络层调试工具(如 tcpdump)完全失效。
- 强制走 TCP 连接:
mysql -h 127.0.0.1 -P 3306 -u root -p
(注意是127.0.0.1,不是localhost) - 验证是否生效:执行
SELECT @@hostname, @@port;,再查SHOW PROCESSLIST;,Host列应显示127.0.0.1:xxxxx而非localhost - 否则你改了
my.cnf的bind-address = 0.0.0.0也白搭,因为根本没走网络栈
用 init_connect 注入调试上下文(慎用)
当需要统一给每个新连接自动设置变量(如 SQL_MODE、时区、或打标记),又不想改应用代码时,init_connect 是唯一选项。但它对 SUPER 权限用户无效,且语句出错会导致连接直接断开。
- 示例:为所有普通连接自动开启
profiling(用于单条语句耗时分析):SET GLOBAL init_connect = 'SET profiling = 1;';
- 必须确保语句语法绝对正确,且不能含 SELECT;推荐先在普通用户连接中手动执行一次验证
- 生产环境禁用,调试完立刻清空:
SET GLOBAL init_connect = '';
- 它不触发
general_log,所以看不到这条语句本身被执行了——这点容易漏掉排查线索
真正难的不是打开这些开关,而是理解它们之间的干扰关系:比如开了 general_log 又连不上,大概率是日志路径不可写;slow_query_log 没内容,可能是 long_query_time 还没刷进全局变量,或者语句压根没进 server 层(比如权限拒绝发生在解析前)。调试环境的价值,永远取决于你能否快速判断“日志为什么没出来”。










