mysql社区版默认完全不记录grant、revoke、create user等权限变更操作;必须启用server_audit插件并配置query_ddl事件才能可靠审计,日志包含user、host、timestamp及完整sql语句。

MySQL 默认不记录权限变更,必须手动启用审计插件
直接回答:GRANT、REVOKE、CREATE USER 这类语句,MySQL 社区版默认**完全不记日志**——general_log 和 binlog 都靠不住。你翻遍 /var/log/mysql/ 也找不到一条权限操作记录,这不是配置错了,是设计如此。
用 server_audit 插件捕获 QUERY_DDL 事件(社区版最稳方案)
这是目前社区版 MySQL 最可靠、最轻量的权限审计方式,核心就三步:
- 确认插件文件存在:
ls /usr/lib/mysql/plugin/server_audit.so(路径可能为/usr/lib64/mysql/plugin/或通过SHOW VARIABLES LIKE 'plugin_dir';查) - 安装并启用:
INSTALL PLUGIN server_audit SONAME 'server_audit.so'; - 关键配置(必须设
QUERY_DDL):SET GLOBAL server_audit_events = 'CONNECT,QUERY_DDL';<br>SET GLOBAL server_audit_logging = ON;<br>SET GLOBAL server_audit_file_path = '/var/log/mysql/audit.log';
⚠️ 注意:QUERY_DML 不管用,它只抓 INSERT/UPDATE/DELETE;只有 QUERY_DDL 才覆盖权限语句。日志里会清晰出现:"query":"GRANT SELECT ON test.* TO 'dev'@'10.0.1.%'",带 user、host、timestamp 字段。
别碰 general_log —— 它不是审计工具,是排查陷阱
虽然 general_log 看似“啥都记”,但它在权限审计场景下基本无效:
- 日志无结构:
GRANT ...和SELECT COUNT(*) FROM orders混在同一行,无法自动提取、过滤或告警 - 无用户上下文分离:所有语句都标记为“连接用户”,但实际执行者可能是代理账号、中间件或应用池,
general_log不记录proxy_user或external_user - 性能爆炸:开启后 QPS 下降 15–30%,日志体积每天 GB 级,磁盘 I/O 成瓶颈
- 不记录执行结果:
GRANT ON nonexistent_db.*失败了?general_log照样记,但没标error_code,你得再查错误日志对齐时间戳
企业版 audit_log 或 Percona Audit Plugin 是替代选项
如果你用的是 MySQL Enterprise Edition,直接配 audit_log.so 更省心:
[mysqld]<br>plugin-load = audit_log.so<br>audit_log_format = JSON<br>audit_log_policy = ALL<br>audit_log_file = /var/log/mysql/audit.log
Percona Server 用户可装 percona-server-audit-plugin,支持 CSV/JSON、按用户/库过滤,且性能比 server_audit 更低。但注意:所有插件都要求重启或至少重载配置,且日志路径目录需 MySQL 进程有写权限(chown mysql:mysql /var/log/mysql),否则插件加载成功但日志静默失败——这个坑很多人踩过。
真正难的不是开日志,而是把日志变成可用线索:轮转策略(server_audit_file_rotate_on_size)、归档脚本、权限控制(chmod 600 /var/log/mysql/audit.log)、与 ELK/Splunk 对接——这些才是上线后马上要补上的动作。










