能,但不推荐在生产环境长期开启;它会记录所有语句,导致i/o压力大、日志爆炸、暴露敏感数据,仅建议临时排障开1–2分钟并立即关闭。

MySQL 自带的 general_log 能不能直接用?
能,但不推荐在生产环境长期开启。它会记录所有语句(包括 SELECT),I/O 压力大、日志体积爆炸、还可能暴露敏感数据。
开启方式:SET GLOBAL general_log = ON;,日志默认写入文件(路径由 general_log_file 控制)或表 mysql.general_log(需设 log_output = 'TABLE')。但表模式下查起来慢,且没有索引优化,SELECT * FROM mysql.general_log 扫全表很卡。
- 只建议临时排障时开 1–2 分钟,立刻关掉:
SET GLOBAL general_log = OFF; - 日志表无主键、无时间索引,按需手动加:
ALTER TABLE mysql.general_log ADD INDEX idx_event_time (event_time);(但 MySQL 8.0+ 对该表结构有限制,部分字段不可修改) - 文件模式下,日志无法按用户/数据库过滤,得靠外部脚本 grep,不灵活
用触发器 + 自定义日志表实现轻量级操作审计
适合记录关键表的增删改(比如用户表、订单表),可控、低侵入、可定制字段。
先建日志表:
CREATE TABLE user_action_log (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
table_name VARCHAR(64) NOT NULL,
action_type ENUM('INSERT', 'UPDATE', 'DELETE') NOT NULL,
pk_value VARCHAR(255) NOT NULL, -- 主键值,字符串兼容 INT/UUID
old_data JSON,
new_data JSON,
operator_user VARCHAR(64),
ip_address VARCHAR(45),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
- 触发器里用
USER()和@@hostname获取操作者信息,但注意:如果是应用连接池统一账号,USER()拿不到真实业务用户,得靠应用层传参写入operator_user -
old_data和new_data用JSON_OBJECT()构造,例如JSON_OBJECT('name', OLD.name, 'email', OLD.email) - 避免在高频写入表上加触发器,否则性能明显下降;单次触发器逻辑别做 HTTP 请求或复杂计算
用 MySQL 8.0+ 的 audit log plugin(企业版)还是社区版替代方案?
MySQL 社区版不带官方 audit plugin(那是企业版功能),但可以用 Percona Server 或 MariaDB 的开源审计插件,或者用 mysqlbinlog 解析 binlog 做事后分析。
-
mysqlbinlog --base64-output=DECODE-ROWS -v mysql-bin.000001可读取行格式 binlog,看到具体变更数据,但它是二进制日志,不是“谁在什么时间做了什么”的语义日志 - binlog 不记录
SELECT、不记录失败语句、不包含客户端 IP,且开启binlog_format = ROW后体积增大,对主从延迟有影响 - 如果真要审计级日志,建议在应用层埋点:ORM 拦截 SQL 执行前后,把
user_id、request_id、sql、params、耗时、结果状态打到 ELK 或本地文件,比 DB 层更准、更可控
日志保留与清理策略怎么定?
没自动清理机制的日志表,半年后就成性能黑洞。别指望 DBA 手动删。
- 用分区表按天/月切分:
ALTER TABLE user_action_log PARTITION BY RANGE (TO_DAYS(created_at)) (...),删除旧分区比DELETE快得多 - 用事件调度器定期清理:
CREATE EVENT cleanup_logs ON SCHEDULE EVERY 1 WEEK DO DELETE FROM user_action_log WHERE created_at - 注意:
DELETE大表会锁表(尤其 MyISAM),InnoDB 虽支持行锁,但大量删除仍引发碎片和事务日志暴涨,优先选TRUNCATE PARTITION或归档后删表
真正难的不是记日志,是定义清楚“哪些操作必须留痕”“保留多久合规”“谁有权查”,技术只是执行环节。字段设计漏了 tenant_id 或 app_version,后期补成本极高。










