必须拥有 super 或 system_variables_admin 权限才能执行 set global general_log = on,否则报 error 1227;log_output 决定日志输出位置,需设为 'file' 或 'table' 并确保路径可写或表可用;开启后须及时关闭以防磁盘和性能崩溃。

确认你真有权限执行 SET GLOBAL general_log = ON
没 SUPER 或 SYSTEM_VARIABLES_ADMIN 权限,这条命令直接报 ERROR 1227 (42501),不是配置不对,是压根没资格开。root 用户默认有,但如果是应用账号或云数据库(如阿里云 RDS),大概率被禁用——RDS 控制台里能点开 general_log 开关,但 SET GLOBAL 会拒绝执行。
先验证权限:
- 运行
SELECT CURRENT_USER();看当前登录身份 - 再跑
SHOW GRANTS;检查输出里是否含SUPER或SYSTEM_VARIABLES_ADMIN - 如果没,别折腾命令,换账号或走管控平台
log_output 决定日志写哪,不配等于白开
SET GLOBAL general_log = ON 只控制“记不记”,不决定“写到哪”。log_output 才是关键变量,它必须是 'FILE' 或 'TABLE'(或两者逗号分隔,但不推荐)。
常见失效场景:
- 执行
SET GLOBAL general_log = ON后查不到日志 → 先SHOW VARIABLES LIKE 'log_output';,如果返回TABLE,但SELECT COUNT(*) FROM mysql.general_log是 0,大概率表引擎异常或被禁用 - 设了
log_output = 'FILE'却没日志 → 检查SELECT @@general_log_file;路径是否存在、MySQL 进程是否有写权限(ls -ld $(dirname $(SELECT @@general_log_file))) - 别用
log_output = 'TABLE'做长期监控:该表默认 CSV 引擎,无索引、不支持DELETE、高并发下易静默丢数据
临时开启必须配好路径和输出目标
动态开启只在本次实例生命周期有效,重启即失效。但若中途没关,下次启动可能继承状态(取决于是否用了 PERSIST,8.0.22+ 支持,但默认不用)。所以每一步都要显式控制:
- 先切输出方式:
SET GLOBAL log_output = 'FILE';(推荐,可控性强) - 再指定文件位置:
SET GLOBAL general_log_file = '/var/log/mysql/general.log';(目录必须存在且 mysql 用户可写) - 最后开日志:
SET GLOBAL general_log = ON; - 立刻验证:
tail -f /var/log/mysql/general.log,另起一个连接执行SELECT 1;,看是否实时出现
注意:general_log_file 路径不能带变量(如 ~)、不能是相对路径,MySQL 不展开。
关不及时,磁盘和性能都会崩
general_log 是全量记录,QPS 1000 的库一小时就能写几个 GB。它不像慢日志有阈值过滤,也不像 binlog 只记事务变更——连 Quit、Connect、Init DB 都记,IO 压力肉眼可见。
排错完必须立刻关:
- 关命令是
SET GLOBAL general_log = OFF;(别写= 0或= 'OFF',虽部分版本兼容,但官方文档明确要求布尔值) - 关了不等于日志文件自动删,
/var/log/mysql/general.log得手动清理或轮转 - 如果之前用过
log_output = 'TABLE',关掉后mysql.general_log表仍保留数据,但新语句不再写入;别靠它做审计,字段argument受max_allowed_packet截断,长 SQL 看不全
最常被忽略的一点:云环境(RDS、PolarDB)的 general_log 文件默认只保留 7 天,且无法修改保留策略。抓包式排查务必卡在窗口期内,别等第二天再去翻日志。











