需先确认 audit_log 插件已加载且状态为 active,再配置 audit_log_file(绝对路径)和 audit_log_policy(如 logins),日志格式依版本选 xml 或 json,记录范围默认不含 select,轮转须用 audit_log_flush 通知 mysql 重开文件。

如何确认 MySQL 是否已加载 audit_log 插件
插件没加载,后续所有配置都白搭。先连上 MySQL 执行:
SHOW PLUGINS;找
audit_log 这一行,Status 必须是 ACTIVE。如果显示 DISABLED 或压根没这行,说明插件没装或没启用。
常见错误现象:改完 my.cnf 重启 MySQL 后,SHOW PLUGINS; 仍看不到 audit_log —— 多半是插件文件路径不对,或者 MySQL 版本不支持(官方 audit_log 插件仅限 MySQL 5.7.20+ 企业版;社区版需用 MariaDB 的 server_audit 或第三方如 Percona 的 audit_log)。
- 检查插件路径:
SELECT @@plugin_dir;,确认audit_log.so(Linux)或audit_log.dll(Windows)真实存在 - 手动加载试试:
INSTALL PLUGIN audit_log SONAME 'audit_log.so';,失败时看错误信息,比如Can't open shared library 'audit_log.so'就是路径或架构不匹配 - MySQL 8.0.19+ 默认禁用所有插件,必须显式
INSTALL PLUGIN,不能只靠配置文件
audit_log_file 和 audit_log_policy 怎么设才有效
audit_log_file 是日志落盘位置,audit_log_policy 控制记录哪些操作。这两项必须在 MySQL 启动前通过配置文件设置(my.cnf 的 [mysqld] 段),运行时无法动态修改(SET GLOBAL 会报错)。
容易踩的坑:把 audit_log_file 设成相对路径(比如 audit.log),MySQL 实际会写到数据目录下,而不是你认为的当前目录;更糟的是权限不足——MySQL 进程用户(如 mysql)必须对目标目录有写权限,否则启动失败且无明确提示。
-
audit_log_policy = ALL记所有连接、查询、断开,日志量爆炸,生产环境慎用;LOGINS只记登录/登出,适合安全合规场景;QUERIES记所有语句但不含连接事件 - 路径务必用绝对路径:
audit_log_file = /var/log/mysql/audit.log,并提前chown mysql:mysql /var/log/mysql - MySQL 5.7 中
audit_log_format = NEW_XML是默认且唯一选项;MySQL 8.0+ 支持JSON格式,但需确认插件版本兼容
为什么 audit_log 不记录 SELECT 或某些 DML
不是 bug,是设计行为。audit_log 默认只记录“影响服务器状态”的操作,比如连接、断开、DDL(CREATE/DROP)、用户管理语句(GRANT/REVOKE)。普通 SELECT、INSERT、UPDATE 默认不记 —— 因为性能代价太高,且审计重点通常是权限变更和结构变动。
如果真需要记录所有查询(例如等保要求),得换思路:audit_log_policy = ALL 确实能覆盖,但会导致磁盘 IO 暴涨、日志文件飞速膨胀。更现实的做法是结合 general_log(开启后记录所有语句,但无结构化字段)或用代理层(如 ProxySQL)做 SQL 级审计。
-
audit_log不区分用户权限,只要语句被执行就可能触发记录(取决于policy),但它不解析 SQL 内容,所以无法按表名、关键词过滤 - 想审计敏感表的读写?得靠应用层埋点 + 数据库中间件,或升级到 MySQL 8.0 的
firewall插件配合规则 - 注意:开启
audit_log后,每个连接建立都会多一次磁盘写,高并发下延迟明显上升,建议单独挂 SSD 盘并限制日志轮转
audit_log 日志怎么查看和轮转
日志是 XML 或 JSON 格式,直接 cat 或 tail 可读性差。别用文本编辑器硬打开大文件,容易卡死;也别指望 MySQL 自带命令解析 —— 它没有 mysqlauditlog 这种工具(那是 Oracle 提供的独立二进制,需额外下载安装)。
真正能落地的方式只有两个:写脚本解析,或用现成的日志收集器。XML 格式可用 xmlstar 命令快速提取字段;JSON 格式推荐 jq。轮转不能靠 logrotate 直接 mv,因为 MySQL 进程还拿着文件句柄,得用 audit_log_flush 命令通知它重新打开新文件。
- 手动轮转步骤:
mysql -e "SET GLOBAL audit_log_flush = ON;"→ 等几秒 →mv /var/log/mysql/audit.log /var/log/mysql/audit.log.$(date +%Y%m%d)→ 再次SET GLOBAL audit_log_flush = ON(触发新建) - logrotate 配置里必须加
postrotate ... mysql -e "SET GLOBAL audit_log_flush = ON;" ... endscript,否则旧日志永远不释放磁盘空间 - XML 日志里关键字段:
NAME="Connect"表登录,NAME="Query"表语句,STATUS="0"表成功,STATUS="1"表失败;JSON 则对应"name":"Connect"等










