通用查询日志开关需在my.cnf中配置general_log=1和general_log_file=/path/to/log,或运行时执行set global general_log = on;但必须确保log_output非none、用户有super权限,且云数据库可能禁用该功能。

通用查询日志开关在哪设?
MySQL 的通用查询日志(General Query Log)默认是关闭的,它会记录所有客户端连接、断开以及每条执行的 SQL 语句(包括 SELECT、INSERT 等),对调试和审计有用,但开启后 I/O 压力明显上升,生产环境慎用。
开启方式只有两种有效路径:启动时配置或运行时动态启用。
- 启动时设置更稳定,适合长期开启;
- 动态开启(
SET GLOBAL general_log = ON)立即生效,但 MySQL 重启后失效; - 单纯改
my.cnf里general_log为1不生效,必须同时指定general_log_file(否则可能写到临时文件或失败)。
实操建议:
- 编辑 my.cnf(通常在 /etc/my.cnf 或 /etc/mysql/my.cnf),在 [mysqld] 段落下添加两行:general_log = 1general_log_file = /var/log/mysql/general.log
- 确保 MySQL 进程有权限写入该路径(比如 chown mysql:mysql /var/log/mysql);
- 重启 MySQL:systemctl restart mysql(或 mysqld);
- 验证是否生效:SHOW VARIABLES LIKE 'general_log%';,输出中 Value 应为 ON 和对应路径。
为什么 SET GLOBAL general_log = ON 有时不生效?
这个命令看似简单,但常被卡在权限或配置冲突上:
- 执行用户必须拥有
SUPER权限(MySQL 5.7+ 中SYSTEM_VARIABLES_ADMIN+SESSION_VARIABLES_ADMIN也可); - 如果
my.cnf中设了general_log = 0,动态开启仍会成功,但日志文件可能为空——因为 MySQL 实际还检查log_output的值; -
log_output默认是FILE,但如果被设成NONE或TABLE(写入mysql.general_log表),而表不存在或权限不足,日志就“静默丢失”; - 某些云托管 MySQL(如阿里云 RDS、AWS RDS)直接禁用通用日志,
SET GLOBAL会报错ERROR 1238 (HY000): Variable 'general_log' is a read only variable。
排查步骤:
- 先查:SELECT @@log_output;,确认不是 NONE;
- 再查:SELECT @@general_log;,确认返回 1;
- 如果写入表模式,检查表是否存在:SHOW CREATE TABLE mysql.general_log;;
- 日志没内容?用 tail -f /var/log/mysql/general.log(或对应路径)实时观察,同时执行一条 SELECT 1; 看是否追加。
日志文件越来越大,怎么安全轮转?
通用日志不会自动切割,放任不管可能撑爆磁盘。MySQL 本身不提供 rotate 机制,得靠外部工具:
- 不要用
echo "" > general.log清空——MySQL 正在写入时会导致文件句柄错位,后续日志可能乱码或丢失; - 正确做法是先关闭日志,重命名文件,再重新打开:
SET GLOBAL general_log = OFF;RENAME TABLE mysql.general_log TO mysql.general_log_old;(仅限log_output=TABLE)
或mv /var/log/mysql/general.log /var/log/mysql/general.log.$(date +%Y%m%d)(log_output=FILE)SET GLOBAL general_log = ON;
- 更稳妥的是用
logrotate配合create和postrotate脚本调用上述SET GLOBAL开关; - 注意:如果用
TABLE输出,清空表(TRUNCATE mysql.general_log)比删表安全,但频繁 TRUNCATE 可能引发锁等待。
要不要把日志写进表(log_output=TABLE)?
写表看起来方便查(SELECT * FROM mysql.general_log ORDER BY event_time DESC LIMIT 10;),但实际坑不少:
-
mysql.general_log是CSV引擎表,不支持索引,大数据量下SELECT极慢; - 每次写入都是一次磁盘同步,性能比写文件更低;
- CSV 表在 MySQL 8.0.23+ 已被标记为 deprecated,未来版本可能移除;
- 如果启用了
sql_log_bin = OFF,写表操作仍会记入 binlog(除非显式SET SQL_LOG_BIN = 0),可能干扰主从复制。
结论:
- 临时调试用 FILE + tail -f 最轻量;
- 审计归档场景,建议用外部日志收集器(如 filebeat)把文件日志推到 ELK;
- 绝对避免在高并发线上库长期开启,哪怕只是写表——它本质仍是全量 SQL 记录,开销无法忽略。
通用日志不是“开了就能用”的开关,它和 log_output、general_log_file、权限、存储引擎、甚至 MySQL 版本强耦合。最常被忽略的是:你以为日志在写,其实它正默默丢弃——先确认 log_output 和文件权限,再看内容。











