要启用 slow_log 表,需同时设置 set global slow_query_log = on 和 set global log_output = 'table';验证方式为查询 select @@slow_query_log, @@log_output 和 select count(*) from mysql.slow_log。

如何启用 slow_log 表并确认是否生效
MySQL 8.0 默认把慢查询日志写入文件,要改到表里,必须开启 slow_query_log 并把 log_output 设为 'TABLE'(不是 'FILE' 或 'FILE,TABLE')。注意:仅设 slow_query_log = ON 不够,log_output 必须显式指定。
执行以下命令:
SET GLOBAL slow_query_log = ON; SET GLOBAL log_output = 'TABLE';
验证是否生效:
查 mysql.slow_log 表是否存在且有数据:SELECT COUNT(*) FROM mysql.slow_log;;再查全局变量:SELECT @@slow_query_log, @@log_output;。如果 @@log_output 返回 'TABLE',说明已切换成功。
常见错误现象:
-
mysql.slow_log表为空,但slow_query_log显示 ON → 很可能log_output还是'FILE',或未触发慢查询(long_query_time默认 10 秒,可临时调低测试) - 报错
Table 'mysql.slow_log' doesn't exist→ MySQL 8.0 默认已建该表,但若曾手动删过,需用mysql_upgrade或重建:CREATE TABLE IF NOT EXISTS mysql.slow_log (...)(不建议手写,应从官方 SQL 模板恢复)
为什么不能同时用 FILE 和 TABLE 输出
MySQL 8.0 不支持 log_output = 'FILE,TABLE' 这种逗号分隔写法——它会静默降级为只写 FILE,mysql.slow_log 不会记录任何内容。这是文档明确说明的限制,不是 bug。
如果你既想保留文件归档又想查表分析,只能二选一,然后靠外部工具同步(比如用 pt-query-digest 解析文件后导入自定义分析表),或者用 MySQL Router / 应用层双写日志。
关键点:
-
log_output是枚举值,合法值只有'FILE'、'TABLE'、'NONE',其他字符串会被忽略 - 修改后无需重启,但新连接才生效;已有连接的会话级日志行为不受影响
- 表输出路径不可配置——固定在
mysql.slow_log,且该表引擎为CSV(8.0.23+ 支持JSON格式但仍是 CSV 引擎存储)
写入 slow_log 表的真实性能开销在哪
写表比写文件慢,但实际影响取决于慢查询频率和并发量,不是“一开就卡”。主要瓶颈来自三处:
- 每次慢查询结束时,MySQL 要构造一条 INSERT 语句并提交到
mysql.slow_log—— 即使该表是 CSV 引擎,仍走事务路径,受innodb_flush_log_at_trx_commit影响(默认 1,强制刷盘) -
mysql.slow_log表没有主键/索引,大量 INSERT 会造成表锁(CSV 引擎本质是表级锁),高并发慢查询下可能堆积 - 日志字段如
sql_text是TEXT类型,若查询超长(比如带大 JSON 或嵌套子查询),写入成本显著上升
实测建议:
若每秒慢查询超过 5–10 次,建议监控 SHOW STATUS LIKE 'Slow_queries'; 和 Threads_running 是否异常升高;必要时可临时关闭 slow_query_log,或改用 performance_schema.events_statements_summary_by_digest 做轻量采样分析。
查 slow_log 表时容易被忽略的细节
直接 SELECT * FROM mysql.slow_log 看起来方便,但有三个硬伤:
-
start_time字段精度只有秒级(不是微秒),无法区分同一秒内多个慢查询 -
sql_text默认被截断(max_length默认 1024 字符),超长部分丢失,查不到完整语句 —— 可通过调整log_slow_extra(8.0.26+)和log_slow_verbosity提升信息量,但不会延长sql_text字段长度 -
mysql.slow_log不自动清理,表会无限增长,必须手动TRUNCATE TABLE mysql.slow_log或按时间分区归档(需自行建视图或脚本)
真正要用它定位问题,得配合 WHERE start_time > DATE_SUB(NOW(), INTERVAL 1 HOUR) 加时间过滤,并留意 query_time 和 lock_time 的差值判断是否真卡在锁上。











