audit_log插件默认不记录mysqldump操作,因其设计仅审计客户端直连语句,而mysqldump走特殊内部路径;即使audit_log_policy=all也无法捕获,需依赖general_log、processlist快照或应用层/代理层日志协同分析。

audit_log 插件默认不记录 mysqldump 操作
MySQL 自带的 audit_log 插件(8.0.19+)明确排除了 mysqldump、mysqlpump 和复制线程产生的 SQL,即使设 audit_log_policy = ALL 也捕获不到。这不是配置遗漏,是插件设计行为——它只审计“客户端直连执行的语句”,而 mysqldump 是工具进程,其内部查询走的是特殊连接路径,不会触发 audit event。
导出操作只能靠 general_log 或 processlist 间接推断
想确认谁在何时导出数据,得换思路:导出必然伴随大量 SELECT(尤其是全表扫描)、SHOW CREATE TABLE、SHOW VARIABLES 等操作,且通常来自短时高并发连接。可行路径有两条:
- 临时开启
general_log:执行SET GLOBAL general_log = ON,并设general_log_file到可写路径;导出期间日志里会出现类似# User@Host: backup[backup] @ 10.0.2.15 [10.0.2.15]的连接头,紧接着是批量SELECT * FROM ...;注意该日志不区分“导出”和“普通查询”,需人工或脚本按时间窗口+用户+高频 SELECT 组合识别 - 导出时抓快照:在
mysqldump执行前后几秒内,快速执行SELECT ID, USER, HOST, COMMAND, TIME, STATE, INFO FROM INFORMATION_SCHEMA.PROCESSLIST WHERE COMMAND = 'Query' AND INFO LIKE 'SELECT%',比对连接来源和 SQL 模式;但无法回溯已结束的导出 - 若用
mysqldump --user=xxx显式指定账户,该用户必须有SELECT权限,且其登录行为会被audit_log记录(前提是走 TCP 连接),可结合record:"connect"+ 时间戳缩小范围
真正能锁定“导出行为”的只有应用层日志或代理层审计
数据库原生能力对此无解,必须跳出 MySQL 本身:
- 在调用
mysqldump的脚本或调度系统(如 Jenkins、Airflow)里加日志:记录执行时间、操作人、目标库表、命令完整参数(含--where等敏感条件) - 前端加审计中间件:比如用 ProxySQL 或 MaxScale 拦截所有客户端连接,配置规则匹配
mysqldump的 User-Agent 字符串(如mysqlslap或自定义 header),并记录原始 IP 和发起时间 - 云数据库(如阿里云 RDS)开启“SQL 审计”后,部分厂商会额外标记导出类工具行为,但依赖控制台开关且保留期短,不能当作可靠依据
audit_log_format=JSON 下如何快速过滤可疑 SELECT?
如果已启用 audit_log 且格式为 JSON,可用以下命令粗筛大查询(不代表导出,但值得人工核查):
grep '"record":"query"' /var/lib/mysql/audit.log | grep -E '"sqltext":"SELECT.*FROM|LIMIT [0-9]{6,}"' | head -20
关键点:
-
"record":"query"表示语句执行事件,不是连接事件 -
"sqltext":"SELECT.*FROM匹配长 SELECT,但无法区分是应用查询还是 dump -
LIMIT [0-9]{6,}是 dump 常见特征(分批导出时加 LIMIT),但手工写 LIMIT 的场景也存在 - JSON 日志每行独立,
grep可用,但不能用jq直接解析整文件——它不是合法 JSON 数组
真正要锁定一次导出,必须把数据库日志、运维操作记录、备份系统日志三者按时间对齐,单靠 MySQL 审计做不到闭环。











