必须启用server_audit插件并配置server_audit_events='CONNECT,QUERY_DDL'才能可靠记录GRANT/REVOKE;社区版无原生审计,需手动安装匹配版本的server_audit.so,且不可与general_log共存。

社区版 MySQL 想可靠记录 GRANT、REVOKE 这类权限变更,必须启用 server_audit 插件,并且 server_audit_events 必须包含 QUERY_DDL —— 其他配置组合基本无效。
确认插件文件存在且路径正确
MySQL 社区版不自带审计能力,server_audit.so 是第三方插件(常见于 Percona Server 或独立编译包),不是 MySQL 官方分发内容。别在默认安装目录里硬找,先查插件路径:
SHOW VARIABLES LIKE 'plugin_dir';
然后进对应目录检查文件是否存在:
-
ls /usr/lib/mysql/plugin/server_audit.so(常见路径) -
ls /usr/lib64/mysql/plugin/server_audit.so(CentOS/RHEL 64 位) - 如果找不到,得手动下载匹配版本的插件(如
server_audit-2.5.1-805-linux-x86_64.zip),解压后确认.so文件权限:chmod +x server_audit.so && chown mysql:mysql server_audit.so
安装并启用 server_audit,关键只设 QUERY_DDL
QUERY_DML 不管用,它只抓 INSERT/UPDATE/DELETE;CONNECT 只记登录登出;真正覆盖权限语句的是 QUERY_DDL。执行以下三步即可生效,无需重启:
INSTALL PLUGIN server_audit SONAME 'server_audit.so';SET GLOBAL server_audit_events = 'CONNECT,QUERY_DDL';SET GLOBAL server_audit_logging = ON;
日志会立刻开始写入,内容类似:
{"time":"2026-04-15T13:45:22","user":"dba@10.0.1.5","query":"GRANT SELECT ON app.* TO 'api'@'%'","host":"10.0.0.1"}注意:server_audit_file_path 默认写到 /var/log/mysql/audit.log,建议显式设置并确保目录存在、属主为 mysql。
为什么不能同时开 general_log?
两个日志机制底层冲突,不是“多记一份更保险”,而是直接拖慢查询、刷爆磁盘、甚至导致连接超时:
-
general_log是全量文本同步写,无缓冲、无轮转控制,每条语句都落盘 -
server_audit是事件驱动,支持server_audit_file_rotate_size轮转,IO 更可控 - 共存时,MySQL 会在同一事务中反复刷两次日志,TPS 明显下降(实测高并发下 QPS 掉 30%+)
- 日志内容重复(比如一条
GRANT既出现在general.log,又出现在audit.log),排查时反而干扰判断
权限变更漏捕获的三个典型场景
即使 server_audit 正常运行,这三类操作也不会出现在日志里:
-
FLUSH PRIVILEGES:它不执行 SQL,只是重载内存权限表,server_audit无法捕获 - 直连修改系统表:如
UPDATE mysql.user SET ...会被记录,但语义模糊——你看到的是 DML,不是原始权限意图 - 存储过程封装权限逻辑:比如
CALL grant_to_team('dev'),日志里只有 CALL 语句,看不到内部实际执行了哪些GRANT
这些都不是配置问题,是审计插件的能力边界。真要覆盖,得在应用层强制走带日志的封装函数,或配合 binlog 解析做二次补全。


















