如何在数据库中保留修改的历史细节(审计跟踪)?

Posted

技术标签:

【中文标题】如何在数据库中保留修改的历史细节(审计跟踪)?【英文标题】:How to keep historic details of modification in a database (Audit trail)? 【发布时间】:2011-02-01 14:37:55 【问题描述】:

我是一名 J2EE 开发人员,我们正在使用带有 PostgreSQL 数据库的休眠映射。

我们必须跟踪数据库中发生的任何更改,换句话说,任何字段的所有先前和当前值都应保存。每个字段可以是任意类型(bytea、int、char...)

使用简单的表格很容易,但我们使用对象图则比较困难。

所以,从 UML 的角度来说,我们有一个对象图,可以在每次更改和用户时存储在数据库中。

任何想法或模式如何做到这一点?

【问题讨论】:

【参考方案1】:

一种常见的方法是存储对象的版本。

如果向要存储审计跟踪的每个表添加“版本”和“已删除”字段,则不要执行正常的更新和删除,请遵循以下规则:

插入 - 将版本号设置为 0 并正常插入。 更新 - 增加版本号并改为插入。 删除 - 增加版本号,将已删除字段设置为 true 并改为执行插入操作。 检索 - 获取版本号最高的记录并返回。

如果您遵循这种模式,每次更新时您都会创建一条新记录,而不是覆盖旧数据,因此您将始终能够回溯并查看所有旧对象。

这对于对象图的工作方式完全相同,只需将新字段添加到对象图中的每个表,并按上述方式处理每个表的每个插入/更新/删除。

如果您需要知道是哪个用户进行了修改,您只需添加一个“ModifiedBy”字段即可。

(您可以在 DA 层代码中执行此处理,或者如果您愿意,可以使用数据库触发器来捕获更新/删除/检索调用并按照规则重新处理它们。)

显然,您需要考虑空间要求,因为每次更新都会产生全新的记录。如果您的应用程序更新繁重,您将生成大量数据。通常还包括“上次修改时间”字段,以便您可以离线处理数据库并删除比要求更旧的数据。

【讨论】:

请记住,这种方法实际上会破坏关系完整性。在常规表中,我们将有一个主键 PK_COL。现在我们的 UID 为 (PK_COL, VERSION_NO)。这使得执行 PK_COL 唯一标识现实世界中某物的规则变得更加困难。它还使外键关系复杂化:如果父记录发生更改(插入新版本),我们是否插入其所有子记录的新版本即使它们都没有更改?最后,这种方法通过要求额外的过滤器来获取当前视图来惩罚最常见的访问路径。 我之前的评论将此作为一种通用的审计方法。可能存储“对象图”的数据库几乎不需要关系完整性,在这种情况下,这种技术可能满足 Mada 的要求。【参考方案2】:

当前的 RDBMS 实现在处理时态数据方面不是很好。这就是为什么通过触发器维护单独的日志表是常用方法的原因之一。 (另一个是审计跟踪经常与常规数据有不同的用例,将它们放在单独的表中可以更容易地管理对它们的访问)。甲骨文在其Total Recall product 中隐藏了管道方面做得非常巧妙,但作为甲骨文,它会为此收取 $$$。

Scott Bailey 发表了一篇关于 PostgreSQL 中时态数据的演示文稿。唉,它现在对您没有帮助,但似乎为 8.5 和 8.6 计划的一些功能将启用与时间相关的数据的透明存储。 Find out more。

【讨论】:

以上是关于如何在数据库中保留修改的历史细节(审计跟踪)?的主要内容,如果未能解决你的问题,请参考以下文章

关于捕获审计跟踪的数据库设计的想法[关闭]

如何在 Visual Studio 中重命名方法并保留历史记录?

如何在简单的 CRUD laravel 中执行简单的审计跟踪

oracle如何启用审计

如何使用trackerenableddbcontext在asp.net mvc5和代码中的实体框架中实现审计跟踪

Spring Data Jpa如何实现审计和乐观锁功能