mysql社区版不支持audit_log插件,应使用server_audit插件或触发器+应用层协同实现敏感操作审计;需确认版本、正确配置路径权限与日志格式,并聚焦connect/disconnect、ddl/dcl及高敏表dml事件。

audit_log 插件在社区版不可用,硬配会启动失败;真正要记录敏感操作,得用 server_audit 或触发器 + 应用层协同,而不是开全量日志。
确认你用的是 MySQL 社区版还是企业版
运行 SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME = 'audit_log';,如果返回空或状态不是 ACTIVE,说明你用的是社区版——audit_log.so 文件即使存在,加载也会失败,错误日志里只报 Can't open shared library,不提示版本限制。
社区版唯一稳妥方案是 server_audit(MariaDB 审计插件),兼容 MySQL 5.7/8.0,文件名通常是 server_audit.so 或 libserver_audit.so:
- 先查插件目录:
SHOW VARIABLES LIKE 'plugin_dir'; - 把
server_audit.so复制到该目录下 - 执行
INSTALL PLUGIN server_audit SONAME 'server_audit.so'; - 检查是否生效:
SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME = 'server_audit';
只记录 connect/disconnect、DDL、DCL 和高敏表 DML
audit_log_policy = ALL 在生产环境几乎不可行:它会记录每条 SELECT 1,IO 压力陡增,日志每天几十 GB;更糟的是,它漏掉 mysqldump、存储过程内部语句等非直连通道操作。
真正要抓敏感行为,聚焦这三类事件:
-
connect/disconnect:识别异常登录时间、来源 IP 频次突增 -
query_ddl(如DROP DATABASE、ALTER TABLE ADD COLUMN)、query_dcl(如GRANT、REVOKE、SET PASSWORD) -
table事件,但仅限指定高敏表(如user_accounts、payment_logs),通过server_audit_events = connect,disconnect,query_ddl,query_dcl,table配置
企业版可用 audit_log_policy = COMMANDS 配合 audit_log_include_accounts 过滤关键账号,社区版没这个选项。
日志路径、权限、格式,三个地方最容易卡住
日志写不进去,90% 不是插件问题,而是路径配置翻车:
-
server_audit_log_file必须是绝对路径(如/var/log/mysql/audit.log),相对路径(如./audit.log)会被忽略 - MySQL 进程用户(如
mysql)必须对目录有写权限,不能写到/root/或/home/xxx/下 - 路径不能含中文、空格、括号;
server_audit_log_file不支持变量替换(如不能写/var/log/mysql/audit_$(date +%F).log) - 格式选
JSON还是NEWLINE影响解析能力:JSON每行一个对象,字段完整,适合 ELK 或 Python 解析,但体积大;NEWLINE是 tab 分隔纯文本,适合grep快筛,但无法表达嵌套结构 -
server_audit_read_buffer_size在 JSON 模式下太小(默认 1M)会导致长 SQL 截断,建议调至4M+
触发器方案只适合关键表的 DML 审计
触发器无法获取 HTTP 请求头、登录用户 ID 或客户端 IP,只能靠应用层提前 SET @audit_user_id = 123 设置会话变量,再在触发器里读取——这意味着连接池(如 HikariCP)必须配置 initSql 或每次获取连接后显式 SET,否则变量可能残留上一个请求的值。
审计日志表结构别贪全:
- 引擎用
ARCHIVE(仅支持 INSERT、压缩率高、无索引)或MyISAM(无事务开销),避免和主表共用 InnoDB 的 redo log 和锁机制 - 必存字段:
operation('INSERT'/'UPDATE'/'DELETE')、table_name、主键值(OLD.id或NEW.id)、exec_time、user_host(可从USER()提取)、client_ip(需应用传入) - 别存整行快照(如
JSON_OBJECT('name', OLD.name, ...))——大字段序列化开销大,且难以后续查询 -
OLD.col != NEW.col对 JSON 字段无效,得用JSON_CONTAINS+JSON_EXTRACT手动比对;OLD.col = NULL永远返回NULL,必须用OLD.col IS NULL
触发器本身不解决登录、权限变更、备份导出这类操作的审计,它只是 DML 行为的补充手段。真正的敏感操作监控,得靠 server_audit 覆盖连接与语句层,再配合独立数据库账号、应用层埋点和定期日志轮转。











