4. 创建服务器审计对象
服务器审计对象是 SQL Server 审计体系的“总闸门”。它本身不定义要记录哪些具体动作,而是先确定审计数据往哪里写、写入时允许多大延迟、写满或失败时怎么办。只有先创建好这个对象,后续的服务器审计规范和数据库审计规范才有落点。本节围绕 CREATE SERVER AUDIT 语句,把目标文件、Windows 安全日志、Windows 应用程序日志三种输出方式,以及队列延迟参数讲清楚。
一、审计对象与审计规范的分工
很多初学者会把“审计对象”和“审计规范”混为一谈。可以这样理解:服务器审计对象负责“管道”,服务器审计规范负责“内容”。一个服务器审计对象可以被多个服务器审计规范引用,所有规范产生的记录都汇入同一个目标。因此,创建审计对象时最需要想清楚的是三件事:数据写到哪里、写入的实时性要求有多高、写入失败时是丢弃还是让操作失败。
审计对象创建后处于禁用状态,必须显式执行 ALTER SERVER AUDIT ... WITH (STATE = ON) 才会真正开始收集。这一点在部署脚本中经常被遗漏,导致规范建好了却没有任何记录。
二、三种目标类型的选择
CREATE SERVER AUDIT 的 TO 子句决定目标类型,可选 FILE、SECURITY_LOG、APPLICATION_LOG。三者的差异直接决定后续的运维方式。
目标文件(FILE)是最常用的方式。审计记录以二进制形式写入指定目录下的 .sqlaudit 文件,支持文件滚动、最大文件大小、最大滚动文件数等参数,容量可控、性能较好,适合绝大多数合规场景。读取时需要用 sys.fn_get_audit_file 函数解析。
Windows 安全日志(SECURITY_LOG)把审计记录写入 Windows 安全事件日志。它的优势是与操作系统安全日志统一管理,便于被 SIEM 采集;代价是写入速度受事件日志机制限制,且需要 SQL Server 服务账户具备“生成安全审核”权限,否则审计对象无法启动。
Windows 应用程序日志(APPLICATION_LOG)写入应用程序事件日志,权限要求相对宽松,但同样存在写入吞吐有限的问题,通常只用于轻量审计或临时排查。
三、队列延迟参数 QUEUE_DELAY 与失败策略
审计记录不是逐条同步落盘的,而是先进入内部队列,再由后台线程批量写出。QUEUE_DELAY 控制这个批量写出的等待时间,单位是毫秒,取值范围 0 到 2147483647,默认 1000。设为 0 表示尽可能接近实时写出,但会显著增加 I/O 压力;设得越大,吞吐越好,但审计记录与真实操作之间的时间差越大,故障时可能丢失队列中尚未落盘的记录。
与队列延迟配套的是 ON_FAILURE 参数,取值 CONTINUE 或 SHUTDOWN。当审计目标不可写(例如磁盘满、目录权限丢失)时,CONTINUE 让数据库继续运行但审计中断,SHUTDOWN 则直接关闭实例,防止在“无审计”状态下继续产生敏感操作。合规要求严格的场景通常选 SHUTDOWN,但必须配套磁盘监控,否则一次磁盘写满就会导致实例停机。
四、创建与启用示例
下面创建一个写入文件的服务器审计对象,队列延迟 1000 毫秒,失败时关闭实例,并设置文件滚动策略。
CREATE SERVER AUDIT [Audit_Compliance_File]
TO FILE
(
FILEPATH = N'D:\SQLAudit\',
MAXSIZE = 256 MB,
MAX_ROLLOVER_FILES = 20,
RESERVE_DISK_SPACE = OFF
)
WITH
(
QUEUE_DELAY = 1000,
ON_FAILURE = SHUTDOWN
);
GO
ALTER SERVER AUDIT [Audit_Compliance_File] WITH (STATE = ON);
GO
若改为写入 Windows 安全日志,语句结构相同,只替换目标子句:
CREATE SERVER AUDIT [Audit_Compliance_SecurityLog]
TO SECURITY_LOG
WITH (QUEUE_DELAY = 1000, ON_FAILURE = CONTINUE);
GO
创建完成后,可用下面的查询确认审计对象状态、目标类型和队列延迟是否符合预期:
SELECT name, type_desc, on_failure_desc,
queue_delay, is_state_enabled
FROM sys.server_audits;
GO
其中 is_state_enabled = 1 表示已启用,queue_delay 应等于设定值。如果为 0 且未启用,说明 ALTER ... STATE = ON 未执行或执行失败。
五、参数取值与运维影响对照
| 参数 | 常用取值 | 影响 |
|---|---|---|
| QUEUE_DELAY | 1000(默认) | 吞吐与实时性的折中,适合多数场景 |
| QUEUE_DELAY | 0 | 近实时,I/O 压力大,高并发下慎用 |
| ON_FAILURE | CONTINUE | 审计中断但实例可用,需告警补偿 |
| ON_FAILURE | SHUTDOWN | 保证不留审计盲区,但可能停机 |
| MAXSIZE | 256 MB | 单文件上限,过小会频繁滚动 |
| MAX_ROLLOVER_FILES | 20 | 滚动文件总数,决定磁盘占用上限 |
需要特别提醒:MAX_ROLLOVER_FILES 与 MAXSIZE 共同决定审计目录的最大占用。上例中约为 256 MB × 20 ≈ 5 GB,规划磁盘时必须预留这部分空间,并设置监控阈值。若设为 UNLIMITED,则文件会持续增长,存在写满磁盘的风险。
六、常见问题与判断依据
创建审计对象时最典型的两类问题:一是执行 CREATE 成功但状态始终为禁用,原因是漏掉了 STATE = ON;二是选择 SECURITY_LOG 后启动失败,报权限相关错误,需要给 SQL Server 服务账户授予“生成安全审核”权限并重启服务。
另一个容易被忽略的点是 FILEPATH 目录必须已存在且服务账户有写权限。SQL Server 不会自动创建该目录,路径不存在时审计对象无法启动。建议在部署脚本中先检查目录,再执行创建语句。
判断审计对象是否真正在工作,不能只看 is_state_enabled,还应确认目标目录下是否已生成 .sqlaudit 文件,或用 sys.fn_get_audit_file 读取到记录。只有“状态启用 + 文件生成 + 可读到记录”三者同时成立,才能认为审计管道已经打通,可以进入下一步创建审计规范。