【发布时间】:2010-11-06 06:59:58
【问题描述】:
如何维护数据库中的数据日志?
我必须维护对每一行所做的每次更改的日志。这意味着我不能让DELETE 和UPDATE 被执行。
我怎样才能保留这样的日志?
【问题讨论】:
标签: database database-design audit
如何维护数据库中的数据日志?
我必须维护对每一行所做的每次更改的日志。这意味着我不能让DELETE 和UPDATE 被执行。
我怎样才能保留这样的日志?
【问题讨论】:
标签: database database-design audit
使用“仅插入数据库”
基本理念是您永远不会更新或删除数据。
每个表都有 2 个日期时间列 from 和 to。
它们以 null 值开始(从时间开始到时间结束)
当您需要“更改”行时添加新行,同时将上一行中的 to 更新为 Now 并将 from 中的您要添加到 Now 的行。
您通过其中包含 where to = null 的视图从表中读取数据。
此方法还可以让您随时了解数据库的状态。
编辑
只是为了回应评论澄清:序列将由表的主键给出,这将是一个自动递增的数字。
【讨论】:
to 和from,它会引入更新异常 - 这是不正确的设计。您只需要存储一个值。
使用“仅插入”数据库,如 Shiraz Bhaji 所述,但您可以使用更简单的技术。对于您需要为其维护审计数据的每个表,只需为更新时间添加一列,默认为现在。当您对记录进行更改而不是更新时,只需插入所有数据即可; UpdatedTime 列将获取当前时间。
请注意,这种方法意味着您必须打破或重新考虑您的 UNIQUE 约束;你可以保留一个主键,但唯一性是你的主键和你的更新时间的组合。
此技术的优点是为您提供表上每条记录的已知历史数据范围(如果每条记录是 WHERE TimeOfInterest > UpdatedTime ORDER BY UpdatedTime DESC 的记录中的前 1 条记录,则每条记录在给定时间有效)低开销(表中只有一列)。从不使用此方法的表进行转换也很容易,只需使用简单的 ALTER TABLE 添加单个列(您可以一致地命名)。然后您只需要更改您的 UNIQUE 约束以使用其当前约束和 UpdatedTime 列的组合,并且需要更改一些查询。
还请注意,如果您创建的表视图仅返回每条记录的最新条目,则实际上可以避免转换所有查询;您最终会得到一个透明地维护历史数据的表,以及一个看起来像没有更改日志的常规表的视图。
【讨论】:
from 和 to 字段之间的不一致而导致的插入异常。
[较晚的帖子,但它添加了此处未提及的两种技术]
读取事务日志 – 如果您的数据库处于完全恢复模式,那么事务日志会存储许多有用的信息,可用于查看每一行的历史记录。 缺点是默认情况下不支持此功能。您可以尝试使用未记录的函数 DBCC LOG 或 fn_dblog 或第三方工具,例如 ApexSQL Log
使用变更数据捕获 - Change data capture 本质上与上面显示的相同,但它更精简且更易于使用。不幸的是,这仅在企业版中可用。
这两者都可以解决允许更新和删除的问题,因为您无法真正更改事务日志中写入的内容。
【讨论】:
一种完全不同的方法是只有一个审核日志。然后,您可以使用它来构建数据的最新版本。您定期创建“检查点”或使用缓存来加快速度。
有一个关于有人使用这种技术的演示文稿:http://www.infoq.com/presentations/greg-young-unshackle-qcon08。这里最大的优势是,由于您只有审核日志,因此您可以确信您的审核跟踪是正确的。
我从来没有尝试过这个,它看起来很复杂......但是需要考虑一下。
【讨论】:
看看我对另一个数据库日志记录问题的回答是否包含您需要的信息。在这里找到它...
History tables pros, cons and gotchas - using triggers, sproc or at application level
【讨论】: