SQL Server审计必须同时启用Server Audit和Database Audit Specification,且DELETE操作需用OBJECT级规则显式指定表(如ADD(DELETE ON dbo.Users BY [public])),否则无法捕获行级删除;日志延迟不可避免,QUEUE_DELAY=0仍可能延迟100–300ms,生产环境应避免设为0,并配合sys.fn_get_audit_file()轮询查日志,重点关注server_principal_name、database_principal_name和session_id字段。
DATABASE AUDIT SPECIFICATION 必须显式指定 DELETE ON dbo.Users BY [public],写成 ADD(DELETE) 会捕获的是数据库级 DDL 删除(比如 DROP TABLE),而不是你关心的行级删除。
SQL Server 审计必须分两层创建:Server Audit + Database Audit Specification
只建 SERVER AUDIT 不会记录任何 DML;只建 DATABASE AUDIT SPECIFICATION 但没启用对应 SERVER AUDIT,日志也完全不会写入。
-
SERVER AUDIT是物理日志载体(决定日志存哪、多大、是否轮转) -
DATABASE AUDIT SPECIFICATION是规则定义(决定监控哪些操作、在哪张表、由谁触发) - 两者都得
ALTER ... WITH (STATE = ON)才真正生效
监控 DELETE 必须用 OBJECT-level 规则,不能靠 SCHEMA 或 DATABASE 级别
写 ADD(DELETE ON SCHEMA::dbo BY [public]) 看似省事,但实际会漏掉跨 schema 的表(比如 sales.Orders)、也不支持细粒度权限控制(如只监看 HR.Employees)。更关键的是,它无法区分“删了哪几行”——审计日志里只有语句模板,没有 WHERE 条件值。
- 精确到表:用
ADD(DELETE ON dbo.Users BY [public]) - 若需监控多个表,每个都要单独
ADD,不能写成ADD(DELETE ON dbo.* ...)(语法不支持) -
BY [public]表示所有拥有该权限的用户,不是指名为public的登录名
日志延迟与性能权衡:QUEUE_DELAY = 0 不等于实时
即使设 QUEUE_DELAY = 0,SQL Server 仍可能因 I/O 压力或锁竞争导致日志写入延迟 100–300ms。而默认 1000ms 延迟在高并发场景下容易丢失最后几条日志(比如事务回滚前已写入审计队列但未刷盘)。
- 生产环境不建议调
QUEUE_DELAY = 0,尤其当每秒 DELETE 超过 50 次时 - 若需准实时定位,应配合
sys.fn_get_audit_file()每 2–3 秒轮询一次,而非依赖“刚删完就查到” - 日志文件路径必须有 SQL Server 服务账户的写入权限,否则审计静默失败(无报错)
查日志时最容易忽略的三个字段
直接查 sys.fn_get_audit_file() 返回结果,光看 statement 和 event_time 不够——真正锁定“谁、何时、删了什么”,得盯住这三个字段:
-
server_principal_name:执行者的登录名(不是数据库用户名) -
database_principal_name:上下文中的数据库用户名(可能为NULL,比如用 Windows 身份直连) -
session_id:可用于关联sys.dm_exec_sessions查客户端 IP 和主机名
注意:如果用户通过应用连接池执行 DELETE,server_principal_name 显示的是连接池账号,不是最终操作人;这时只能靠应用层埋点或结合网络层日志交叉验证。