我正在尝试创建一些功能,以跟踪给定用户表单中的数据如何随时间变化的审计跟踪,并在该页面的底部进行了过时的审计。例如:
2009 年 2 月 4 日 21:49 名称从“汤姆”更改为“克里斯”。
我这样做是通过在会话中以当前格式存储数据,然后在保存时检查存储的数据是否有任何差异。如果有,我将数据在最近一次编辑之前的状态存储在一个名为历史的表中,并将新值存储在当前用户表中。
这是最好的方法吗?
我不确定是否有一种“最佳方法”,有很多变量需要考虑,包括您的开发路径有多远。
通过基于代码和 db-trigger 审计解决方案,我在下面列出了一些评论;我希望你能看到你现在所处的位置(在发展方面)可能会影响这些问题:
一个建议;这在数据库触发器中相对容易做到。在这种情况下,您永远不必担心运行更新的代码是否记得添加历史记录。
我一直喜欢使用一个表,而不是将其分解为“活动”表和“历史”表。我在这些表上放了 4 列,所有时间戳:创建、删除、开始、结束。“创建”和“删除”是不言自明的。“开始”和“结束”时间戳用于记录实际上是“活动”记录的时间。当前活动的记录将具有之前的“开始”时间now()
和NULL
“结束”时间。通过分离“创建”和“开始”时间,您可以安排将来发生的更改。
与两表设计相反,这种设计允许您轻松编写将自动对正确数据进行操作的查询。假设您的表随着时间的推移存储税率......您不希望在计算中使用税率的所有查询都具有额外的复杂性,即在处理旧发票时决定在历史表中查找内容,例如例如...您可以在一个查询中查找发票创建时的有效税率,无论它是否是当前税率。
这个想法最初不是我的(尽管在阅读之前我确实自己重新发明了这个粗略的想法)......你可以在这本在线书籍中找到关于它的详细讨论。
会话参与让我有点警惕(当两个用户同时处理相同的数据时,你确定你处理得当吗?),但总的来说,是的,保留历史表是正确的。
我还会考虑插入或更新时的数据库触发器,以将更改详细信息(谁、何时、什么、之前的值、之后的值)记录到单独的审计表中。这样您就知道,即使直接使用数据库在您的应用程序之外更改数据,它仍然会被拾取。
您可能还想做一些事情来检测数据是否在您的应用程序之外更改,例如计算记录的哈希或 crc 并将其存储在某处的字段中,然后在读取数据时检查它。
我认为您的建议将涉及编写大量代码/元数据以启用对象/记录的比较,以便您获得业务级别的审计。
或者,数据库触发器可能无法让您对所发生的事情有足够的了解。如果您很少使用审计以致重新创建业务意义的努力是可以接受的,这可能是可以接受的。
这似乎也是 AOP(方面)的一个很好的应用程序,您可以在对象模型上使用反射来转储有意义的东西,而无需大量元数据。