临时开启 general_log 只需执行 SET GLOBAL general_log = ON,立即生效且无需重启;它会记录所有SQL及连接事件,但生产环境慎用以防磁盘写满。

怎么临时打开 general_log 记录所有 SQL?
直接连上 MySQL,用 SET GLOBAL general_log = ON 就能立刻生效,不用重启。这是最快速验证问题的方式,比如你刚执行了一条 SELECT 却没看到结果,怀疑被拦截或没走预期逻辑,开这个日志一眼就能确认客户端到底发了什么。
但要注意:general_log 默认关着,而且它记录的是「所有」语句——包括 SHOW PROCESSLIST、PING、心跳包,甚至连接/断开事件。在生产环境随手一开,几小时就可能写满磁盘。
-
SET GLOBAL general_log_file = '/tmp/mysql-general.log'可指定路径,务必确保 MySQL 进程对目标目录有写权限(常见坑:路径存在但属主是root,而mysqld以mysql用户运行) - 开完立刻查状态:
SHOW VARIABLES LIKE 'general_log%',确认Value是ON且文件路径无误 - 关掉只需
SET GLOBAL general_log = OFF,无需重启,也不影响其他日志
如何永久启用并控制日志落盘位置?
编辑 MySQL 配置文件(Linux 是 /etc/my.cnf 或 /etc/mysql/my.cnf,Windows 是 my.ini),在 [mysqld] 段落下加两行:
general_log = ON general_log_file = /var/log/mysql/general.log
然后重启 mysqld。注意:MySQL 5.7+ 不再支持旧式 log = xxx 写法,必须用 general_log;如果配置后不生效,大概率是配置文件没加对段落,或者服务读的是另一个 my.cnf(可用 mysqld --help --verbose | grep "Default options" 查实际加载路径)。
- 日志文件不会自动轮转,长期开启必须配合外部工具(如
logrotate)定期切割,否则单个文件可能达几十 GB - 默认日志格式是纯文本,不带时间戳;若需精确到毫秒级时间,得搭配
log_timestamps = SYSTEM(MySQL 8.0.14+) - 别把日志和数据目录放一起——万一磁盘写满,MySQL 可能直接挂起,连
SHUTDOWN都执行不了
为什么 general_log 不适合线上长期开着?
它不是性能监控工具,而是调试放大镜。每条语句、每个连接握手、每次认证失败都会写入,I/O 压力直线上升。实测在 QPS 200+ 的业务库上开启后,磁盘写入延迟跳高 3–5 倍,部分慢查询反而被掩盖在海量日志写入中。
- 替代方案更务实:查登录行为看
error log(含认证失败)、查低效 SQL 用slow_query_log+long_query_time = 0.1(记录所有超 100ms 的查询) - 如果真要审计所有操作,优先考虑
binlog(事务安全、可重放、自带压缩),但注意它不记录SELECT和SET类语句 - 某些云数据库(如阿里云 RDS)干脆禁用了
general_log的动态开关,只允许通过控制台开启并限时 24 小时,就是防误操作
日志文件写不进去?先检查这三件事
权限、路径、SELinux —— 90% 的“开了没日志”问题卡在这儿。
- 用
ps aux | grep mysqld看进程用户(通常是mysql),再ls -ld /var/log/mysql确认该用户对该目录有w权限 - 路径别用
~或相对路径,general_log_file必须是绝对路径,且父目录得存在(MySQL 不会自动创建多层目录) - CentOS/RHEL 上跑 SELinux 的话,
setsebool -P mysqld_disable_trans on或给日志目录打标:semanage fcontext -a -t mysqld_log_t "/var/log/mysql(/.*)?",否则会被静默拦截
真正麻烦的不是怎么开,而是怎么关得干净——关掉 general_log 后,已打开的文件描述符仍被持有,rm 文件名只是删了链接,空间不会释放,得靠 kill -USR1 或重启 MySQL 才能彻底清空句柄。











