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 / DDLDELETE
对象数据库名.表名orders.payment
SQL语句(或摘要)完整SQL或参数化后的模板DELETE FROM orders WHERE id = ?
受影响行数DML操作影响的行数15230
执行结果成功 / 失败(含错误码)success

我个人习惯称它为“数据库的摄像头”。但要注意——摄像头拍得越清晰,存储成本越高,对数据库性能的影响也越大。怎么平衡?后面我们会细聊。

1.2 审计日志的作用

我把它总结成三大块:

  • 事后追溯——出了安全事件,能快速定位问题范围。我曾经帮一家金融客户排查数据泄露,就是靠审计日志定位到某台跳板机被种了远控,在凌晨两点批量查客户信息。
  • 合规审计——等保2.0、GDPR、SOX,这些法规都要求保留操作记录。审计日志就是给监管看的那张“考卷答案”。
  • 主动异常检测——这才是我们这门课的核心。你想想,如果把审计日志实时流入分析引擎,你就能在攻击发生几分钟甚至几秒内发现异常行为,比如某个平时只读数据的账号突然开始大量删除。

核心观点:审计日志不仅是“事后诸葛亮”的工具,更是“事前预警”的数据基础。没有它,异常检测就是无源之水。

1.3 常见数据库审计机制

不同的数据库,审计的实现方式差异很大。我画了一张图帮你看清它们的关系:

常见数据库审计机制对比 常见数据库审计机制 MySQL PostgreSQL Oracle general_log audit_log init_connect log_duration pgaudit log_statement AUDIT命令 FGA Unified Audit 选择建议:MySQL用audit_log插件,PostgreSQL用pgaudit,Oracle用Unified Audit

下面我分别聊聊这三种数据库的审计机制该怎么配,以及我踩过的坑。

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只记敏感表)。
  • 评估存储开销和性能影响。
  • 制定日志轮替和归档策略。
  • 把审计数据接入分析系统——这才是异常检测的前提。

特别提醒: 审计日志本身也是敏感数据。我见过有公司把审计日志明文存在同个数据库里,等于把监控录像放在小偷家里。建议审计日志独立存储、加密传输,并限制访问权限。