这是创建审计跟踪的最佳方法吗?

时间:2009-04-02 20:57:27

标签: php mysql audit

我正在尝试创建一些功能,以便对给定用户表单中的数据如何随时间变化进行审计跟踪,并在该页面的底部进行过时的审计。例如:

02/04/09 21:49名称从“Tom”改为“Chris”。

我这样做是通过在会话中以数据的当前格式存储数据然后保存检查存储的数据是否存在任何差异。如果有,我将数据存储在名为history的表中最新编辑之前的数据,并将新值存储在当前用户表中。

这是最好的方法吗?

6 个答案:

答案 0 :(得分:11)

我不确定是否有一种“最佳方法”,需要考虑很多变量,包括你的开发路径有多远。

通过基于代码和数据库触发器的审计解决方案,我在下面列出了一些评论;我希望你能看到你现在所处的位置(就发展而言)可能会影响这些问题:

  • 如果您需要映射更改数据的用户(您通常这样做),那么db触发器将需要以某种方式获取此信息。并非不可能,但需要更多工作和几种方法(db用户执行查询,每个表中的公共用户列等)。
  • 如果您使用数据库触发器,并且依赖于从查询返回的受影响的行数,则您的审核触发器需要关闭此功能,或者修改现有代码以对其进行说明。
  • IMHO数据库触发器提供更多安全性,并提供更简单的审计自动化路径,但它们并非万无一失,因为任何具有适当访问权限的人都可以禁用触发器,修改数据然后再次启用它们。换句话说,确保您的数据库安全访问权限很紧。
  • 如果要审核多个表的历史记录,特别是在重构审计跟踪时,如果要审计多个表的历史记录,那么拥有一个历史记录表并不是一个糟糕的方法,尽管您还有更多的工作要做(以及要存储的数据)。如果有许多表试图写入一个审计表,您还必须考虑锁定问题。
  • 拥有每个表的审核历史记录表是另一种选择。您只需要审计表中的每一列都可以为空,以及存储操作的日期和时间(插入/更新/删除)以及与操作关联的用户。
  • 如果你选择单表选项,除非你有足够的时间花在这上面,不要过于花哨试图只审计更新或删除,尽管它可能很容易避免插入(因为大多数应用程序比更新或删除更经常这样做,重建审计历史需要相当多的工作。
  • 如果您的服务器或数据跨越多个时区,请考虑使用适当的日期时间类型来存储和重建时间线,即以UTC格式存储审核事件日期以及包括时区偏移。
  • 这些审计表可能会变得庞大,因此如果它们开始影响性能,请制定策略。选项包括将表分区到不同的光盘上,存档等等。现在基本上考虑这个问题,而不是当它成为一个问题时:)

答案 1 :(得分:5)

一个建议;这在数据库触发器中相对容易。在这种情况下,您永远不必担心运行更新的代码是否记得添加历史记录。

答案 2 :(得分:3)

我一直喜欢使用一个表而不是将其分解为“活动”表和“历史”表。我在这些表上放了4列,所有时间戳:创建,删除,开始,结束。 “创建”和“删除”是相当不言自明的。 “开始”和“结束”时间戳是指记录实际上是“活动”记录的时间戳。当前有效的记录将在now()NULL“结束”时间之前具有“开始”时间。通过分离“创建”和“开始”时间,您可以安排将来进行更改。

与双表设计相反,此设计允许您轻松编写将自动操作正确数据的查询。假设您的表格随时间存储税率...您不希望在计算中使用税率的所有查询都具有在处理旧发票时决定在历史表中查找内容的额外复杂性,示例...您可以查询在一个查询中创建发票时生效的税率,无论它是否是当前税率。

这个想法本来不是我的(尽管我在阅读之前就已经自己重新发明了这个粗略的想法)......你可以在online book中找到对它的详细讨论。

答案 3 :(得分:0)

会话参与让我有点警惕(你确定当两个用户同时处理相同的数据时你正确处理它吗?),但总的来说,是的,保留历史表是正确的的事情。

答案 4 :(得分:0)

我还会考虑插入或更新时的数据库触发器,以便将更改详细信息(who,when,what,value,value after)记录到单独的审计表中。这样你就知道,即使你的应用程序使用数据库直接更改了数据,它仍然会被接收。

您可能还想做一些事情来检测您的应用程序是否更改了数据,例如计算记录的哈希值或crc并将其存储在某个字段中,然后在读取数据时进行检查。

答案 5 :(得分:0)

我认为您的提案会涉及编写大量代码/元数据以实现对象/记录的比较,以便您进行业务级别的审核。

或者,数据库触发器可能无法为您提供足够高级别的视图。如果你很少使用审计来重新创建业务意义的努力是可以接受的,那么这是可以接受的。

这似乎也是AOP(Aspects)的一个很好的应用程序,你可以在对象模型上使用反射来转储有意义的东西,而不需要大量的元数据。