1. 数据库审计日志概述
先问个问题:你管数据库的时候,有没有半夜被电话吵醒过?我就有过。那天凌晨三点,某张订单表突然被删了十几万行。查了半天,既没找到操作人,也说不清时间线。后来才明白——审计日志没开。
审计日志,说白了就是数据库里的一本“黑匣子”。谁、在什么时间、从哪个IP、执行了什么SQL、影响了多少行,全都一笔一笔记下来。我见过不少团队,平时觉得审计日志“浪费性能”,等出了事才后悔没开。嗯,典型的“事后诸葛亮”。
1.1 什么是审计日志
审计日志不是普通的慢查询日志或错误日志。它专门记录与安全相关的数据库活动。你想想看,数据库里存着客户手机号、银行卡、交易记录。如果被人偷偷拖了一次库,甚至删了表,没有审计日志,等于犯罪现场没监控。
一个完整的审计日志条目,通常包含这些字段:
| 字段 | 说明 | 示例 |
|---|---|---|
| 时间戳 | 操作发生的精确时间 | 2025-03-21 14:23:45.123 |
| 会话ID | 数据库连接的唯一标识 | 527483 |
| 用户 | 认证用户名或操作系统用户 | app_user |
| 源IP | 客户端IP地址 | 10.0.1.45 |
| 操作类型 | SELECT / INSERT / UPDATE / DELETE / DDL | DELETE |
| 对象 | 数据库名.表名 | orders.payment |
| SQL语句(或摘要) | 完整SQL或参数化后的模板 | DELETE FROM orders WHERE id = ? |
| 受影响行数 | DML操作影响的行数 | 15230 |
| 执行结果 | 成功 / 失败(含错误码) | success |
我个人习惯称它为“数据库的摄像头”。但要注意——摄像头拍得越清晰,存储成本越高,对数据库性能的影响也越大。怎么平衡?后面我们会细聊。
1.2 审计日志的作用
我把它总结成三大块:
- 事后追溯——出了安全事件,能快速定位问题范围。我曾经帮一家金融客户排查数据泄露,就是靠审计日志定位到某台跳板机被种了远控,在凌晨两点批量查客户信息。
- 合规审计——等保2.0、GDPR、SOX,这些法规都要求保留操作记录。审计日志就是给监管看的那张“考卷答案”。
- 主动异常检测——这才是我们这门课的核心。你想想,如果把审计日志实时流入分析引擎,你就能在攻击发生几分钟甚至几秒内发现异常行为,比如某个平时只读数据的账号突然开始大量删除。
核心观点:审计日志不仅是“事后诸葛亮”的工具,更是“事前预警”的数据基础。没有它,异常检测就是无源之水。
1.3 常见数据库审计机制
不同的数据库,审计的实现方式差异很大。我画了一张图帮你看清它们的关系:
下面我分别聊聊这三种数据库的审计机制该怎么配,以及我踩过的坑。
MySQL审计
MySQL的审计能力比较“分裂”。社区版只有 general_log(记录所有查询)和 slow_query_log(记录慢查询),但这两个都不是真正的审计日志。为什么要强调这个?general_log把所有连接和SQL都记下来,在高并发下磁盘I/O会瞬间爆炸。我记得有一次线上开了general_log,QPS直接掉了30%。
真正的审计方案是:
- MySQL Enterprise Audit(商业版提供)——基于插件
audit_log.so,支持按用户、数据库、对象级别过滤。 - MariaDB Audit Plugin——开源,功能与商业版接近。我个人的经验是:如果公司买不起企业版,用MariaDB的插件也够用,注意要编译到MySQL里。
- 通用日志 + 解析工具——用
init_connect记录连接信息,再配合binlog做增量数据回溯。
避坑指南:我曾经接手一个项目,开发为了审计直接开了general_log,结果磁盘撑爆。建议对生产环境务必使用基于规则的审计插件,只记录可疑操作(比如删除、DDL、未授权的查询),而不是全量记录。
PostgreSQL审计
PostgreSQL自带的日志功能其实比MySQL丰富,但默认配置只记错误和连接。要打开真正的审计,得调几颗“螺丝”:
| 参数 | 用途 | 推荐值(生产) |
|---|---|---|
| log_duration | 记录每条语句的执行时间 | on |
| log_statement | 记录SQL语句(none/ddl/mod/all) | ddl(避免全量记录) |
| log_connections | 记录用户登录 | on |
| log_disconnections | 记录用户登出 | on |
但这些还不够。如果你需要细粒度审计(比如记录某个表的所有SELECT),必须用pgaudit扩展。pgaudit是PostgreSQL官方推荐的审计扩展,支持按角色、按对象、按SESSION级别审计。
它的配置有点反直觉:你得先 shared_preload_libraries = 'pgaudit',然后重启数据库。没错,要重启。第一次搞这个的时候,我以为是配置错了,折腾了大半天。后来学乖了——先在测试库上改,验证配置完再给生产用。
一句话: PostgreSQL审计,不开pgaudit等于只戴了口罩没穿防护服。
Oracle审计
Oracle的审计机制是三家里最成熟的,但也最复杂。简单梳理:
- 传统审计(AUDIT命令)——SQL语句级审计。比如
AUDIT SELECT ON hr.employees BY scott;。但有个坑:如果审计策略太多,会导致系统表AUD$暴涨,清理不及时会撑爆SYSTEM表空间。 - 细粒度审计(FGA)——可以基于列值做条件审计。比如“当薪资列大于50000时记录”。这个灵活,但性能开销也不小。
- 统一审计(Unified Audit)——Oracle 12c以后推荐的方式。所有审计记录统一写到
AUDSYS表空间,支持混合审计策略。我个人强烈建议新项目用统一审计。
我曾经处理过一个Oracle生产事故:传统审计没开自动清理,AUD$表占用了200GB,导致归档日志爆满,数据库挂起。从那以后,我带的项目都会写一个审计日志清理脚本,定时 truncate 或者 purge。
总结一下
审计日志不是锦上添花的东西,而是数据库安全的“底线防守”。不管用哪种数据库,我建议你在一开始就规划好审计策略:
- 明确要记录什么类型的操作(DDL必须、DML按需、SELECT只记敏感表)。
- 评估存储开销和性能影响。
- 制定日志轮替和归档策略。
- 把审计数据接入分析系统——这才是异常检测的前提。
特别提醒: 审计日志本身也是敏感数据。我见过有公司把审计日志明文存在同个数据库里,等于把监控录像放在小偷家里。建议审计日志独立存储、加密传输,并限制访问权限。