在业务系统中,物理删除数据往往会导致关键信息丢失,难以满足审计与合规要求。通过SQL结合审计日志表与CDC变更数据捕获,可以在Delete发生时自动留存被删记录。下面先了解一种常见的实现思路。

为什么需要在Delete时记录审计日志
当操作员或定时任务执行删除时,如果没有任何记录,后续无法知道谁删除了什么数据、删除前的内容是什么。审计日志配合CDC可以解决这一问题:
- 满足内部合规与外部监管对数据操作可追溯的要求
- 在误删时支持快速还原
- 通过CDC降低对主业务代码的侵入
基于触发器的审计日志实现
最简单的方式是使用SQL触发器,在Delete事件中将旧行写入审计表。假设我们有用户表 user_info,先建立审计表:
CREATE TABLE user_info (
id INT PRIMARY KEY,
name VARCHAR(50),
email VARCHAR(100)
);
CREATE TABLE user_info_audit (
audit_id BIGINT IDENTITY(1,1) PRIMARY KEY,
deleted_id INT,
deleted_name VARCHAR(50),
deleted_email VARCHAR(100),
deleted_at DATETIME,
deleted_by VARCHAR(50)
);
然后创建Instead Of或After Delete触发器,将删除的数据转入审计表:
CREATE TRIGGER trg_user_info_delete
ON user_info
AFTER DELETE
AS
BEGIN
INSERT INTO user_info_audit
(deleted_id, deleted_name, deleted_email, deleted_at, deleted_by)
SELECT
d.id,
d.name,
d.email,
GETDATE(),
SYSTEM_USER
FROM deleted d;
END;
应用CDC变更数据捕获
触发器方案简单但会增加事务开销。SQL Server等数据库提供原生CDC功能,可异步捕获所有变更。开启数据库和表级CDC:
EXEC sys.sp_cdc_enable_db;
EXEC sys.sp_cdc_enable_table
@source_schema = 'dbo',
@source_name = 'user_info',
@role_name = NULL;
启用后,系统会生成 cdc.dbo_user_info_CT 变更表,Delete操作会以 __$operation = 1 记录。可定期将操作类型为删除的变更同步到审计库:
INSERT INTO user_info_audit
(deleted_id, deleted_name, deleted_email, deleted_at, deleted_by)
SELECT
c.id,
c.name,
c.email,
c.__$start_lsn_time,
'cdc_capture'
FROM cdc.dbo_user_info_CT c
WHERE c.__$operation = 1;
触发器与CDC的对比
| 方式 | 实时性 | 性能影响 | 实现复杂度 |
|---|---|---|---|
| 触发器 | 高 | 较大 | 低 |
| CDC | 近实时 | 较小 | 中 |
注意事项
无论采用哪种方案,都应注意审计表本身的保护,避免被二次删除。同时建议对审计表做只读权限控制,并定期归档历史数据。
在设计删除审计时,明确保留周期与脱敏规则,避免审计库膨胀或泄露敏感信息。
小结
通过SQL触发器可以快速实现Delete审计,而CDC更适合大型系统低侵入捕获。实际项目中可组合使用:触发器保底,CDC做异步分析。