编程数据库开发人员

如何实现和正确使用日志表(log tables)以审计 SQL 生产数据库中的更改?存在哪些潜在问题,如何最小化它们对性能的影响?

用 Hintsage AI 助手通过面试

回答。

更改日志表(log/audit tables)是普通表格,用于保存生产表格中数据更改事件的信息:谁、何时以及更改了什么。这对于金融行业、电子商务、政府机构尤为重要。

实现方法

  1. 通过应用程序或过程显式记录到日志。
  2. 使用触发器跟踪任何更改。
  3. 在新数据库中,使用更改数据捕获(Change Data Capture, CDC)或时间表(Temporal Tables)系统机制。

典型组成

  • audit_id (PK), TableName, OperationType (I/U/D), RecordID, OldValue, NewValue, ChangedBy, ChangeDT

示例代码(UPDATE审计触发器)

CREATE TABLE ProductAudit ( AuditID int IDENTITY(1,1) PRIMARY KEY, ProductID int, OldPrice money, NewPrice money, ChangedBy sysname, ChangeDT datetime, OperationType char(1) ); GO CREATE TRIGGER trg_ProductAudit ON Products AFTER UPDATE AS BEGIN INSERT INTO ProductAudit(ProductID, OldPrice, NewPrice, ChangedBy, ChangeDT, OperationType) SELECT d.ProductID, d.Price, i.Price, SYSTEM_USER, GETDATE(), 'U' FROM inserted i JOIN deleted d ON i.ProductID = d.ProductID WHERE i.Price <> d.Price; END

潜在问题

  • 审计表的巨大体积可能会减慢查询速度。
  • 需要合理的分区/删除旧数据。
  • 需要关注锁定和去重更改。

具有挑战性的问题。

问:在回滚主要事务时,log表中的记录是否会自动撤销?

答: 如果触发器是事务的一部分,那么是的,日志的插入会与主要操作一起回滚。然而,在应用程序/单独事务级的日志记录中,可能不会保持一致性。

由于对该主题细微差别的不熟悉而导致的实际错误示例。


故事

在一家信贷机构中,未实现审计表的清理机制。导致表的行数超过了数亿,造成备份时间长、空间不足和整个数据库的性能下降。


故事

开发人员通过单独的连接在事务外执行审计。因此,出现了不存在的事件记录(应用逻辑的事务被回滚,而日志中的记录则没有)。


故事

在设计更改日志时,为所有字段引入了 NVARCHAR(MAX) 类型,以便于通用性。但这并不需要,反而增加了存储和索引的负担——数据无法有效分析。