简体   繁体   English

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

[英]Is this the best approach to creating an audit trail?

I'm trying to create some functionality that keeps an audit trail of how data in a given user form has been changed over time, with a dated audit at the foot of that page. 我正在尝试创建一些功能,以便对给定用户表单中的数据如何随时间变化进行审计跟踪,并在该页面的底部进行过时的审计。 For example: 例如:

02/04/09 21:49 Name changed from "Tom" to "Chris". 02/04/09 21:49名称由“Tom”改为“Chris”。

I'm doing this by storing the data in it's present format in the session and then on save checking whether there are any differences in the data being stored. 我这样做是通过在会话中以数据的当前格式存储数据,然后在保存时检查存储的数据是否存在任何差异。 If there are, I'm storing the data how it was before the latest edit in a table called history, and storing the new values in the current user table. 如果有,我将数据存储在名为history的表中最新编辑之前的数据,并将新值存储在当前用户表中。

Is this the best approach to be taking? 这是最好的方法吗?

I'm not sure there is one "best approach", there are so many variables to take into consideration, including how far down the development path you are. 我不确定是否有一个“最佳方法”,需要考虑很多变量,包括你的开发路径有多远。

Having been through both code-based and db-trigger auditing solutions, I've listed some comments below; 通过基于代码和数据库触发器的审计解决方案,我在下面列出了一些评论; I hope you can see where you are now at (in terms of development) could affect these issues: 我希望你能看到你现在所处的位置(在开发方面)会影响这些问题:

  • If you need to map the user who changed the data (which you normally do) then db triggers will need to get this information somehow. 如果您需要映射更改数据的用户(您通常会这样做),那么db触发器将需要以某种方式获取此信息。 Not impossible, but more work and several ways to approach this (db user executing query, common user column in each table, etc.) 并非不可能,但需要更多的工作和几种方法(db用户执行查询,每个表中的公共用户列等)
  • If you use db triggers and you rely on affected rows count returned from queries, then your audit triggers need to have this turned off, or your existing code modified to account for them. 如果您使用数据库触发器并依赖于从查询返回的受影响的行数,则您的审计触发器需要关闭此选项,或者修改现有代码以解决这些问题。
  • IMHO db triggers offer more security, and offer an easier path to audit automation, however they are not foolproof, as anyone with appropriate access can disable the triggers, modify data and then enable them again. IMHO数据库触发器提供更多安全性,并提供更简单的审计自动化路径,但它们并非万无一失,因为任何具有适当访问权限的人都可以禁用触发器,修改数据然后再次启用它们。 In other words, ensure your db security access rights are tight. 换句话说,确保您的数据库安全访问权限很紧。
  • Having a single table for history is not a bad way to go, although you will have more work to do (and data to store) if you are auditing history for multiple tables, especially when it comes to reconstructing the audit trail. 拥有一个历史记录表并不是一个糟糕的方法,但如果您要审计多个表的历史记录,尤其是在重建审计跟踪时,您将有更多工作要做(以及要存储的数据)。 You also have to consider locking issues if there are many tables trying to write to one audit table. 如果有许多表试图写入一个审计表,您还必须考虑锁定问题。
  • Having an audit history table for each table is another option. 拥有每个表的审计历史记录表是另一种选择。 You just need each column in the audit table to be nullable, as well as storing date and time of action (insert/update/delete) and the user associated with the action. 您只需要审计表中的每一列都可以为空,以及存储操作的日期和时间(插入/更新/删除)以及与操作关联的用户。
  • If you go with the single table option, unless you have a lot of time to spend on this, don't get too fancy trying to audit only on updates or deletes, although it may be tempting to avoid inserts (since most apps do this more often than updates or deletes), reconstructing the audit history takes a fair bit of work. 如果你选择单表选项,除非你有足够的时间花在这上面,不要过于花哨试图只审计更新或删除,尽管它可能很容易避免插入(因为大多数应用程序都这样做)通常比更新或删除更重要,重建审计历史需要相当多的工作。
  • If your servers or data span multiple time-zones, then consider using an appropriate datetime type to be able to store and reconstruct the timeline, ie store audit event date in UTC as well as including the timezone offset. 如果您的服务器或数据跨越多个时区,则考虑使用适当的日期时间类型来存储和重建时间线,即以UTC格式存储审计事件日期以及包括时区偏移。
  • These audit tables can get huge, so have a strategy if they start affecting performance. 这些审计表可能会变得很大,因此如果它们开始影响性能,请制定策略。 Options include table partitioning onto different discs, archiving, etc. basically think about this now and not when it becomes a problem :) 选项包括将表分区到不同的光盘上,存档等等。现在基本上考虑这个,而不是当它成为问题时:)

One suggestion; 一个建议; this would be relatively easy to do in a database trigger. 这在数据库触发器中相对容易。 In that case, you would never have to worry about whether the code running the update remembers to add a history record. 在这种情况下,您永远不必担心运行更新的代码是否记得添加历史记录。

I've always been a fan of using one table instead of breaking it up into an "active" table and a "history" table. 我一直是使用一个表而不是将其分解为“活动”表和“历史”表的粉丝。 I put 4 columns on these tables, all timestamps: created, deleted, start, end. 我在这些表上放了4列,所有时间戳:创建,删除,开始,结束。 "created" and "deleted" are fairly self-explanatory. “创建”和“删除”是相当不言自明的。 The "start" and "end" timestamps are for when the record was actually the "active" record. “开始”和“结束”时间戳是指记录实际上是“活动”记录的时间戳。 The currently-active record would have a "start" time prior to now() and a NULL "end" time. 当前活动的记录将具有now()之前的“开始”时间和NULL “结束”时间。 By separating out the "created" and "start" times, you can schedule changes to take place in the future. 通过分离“创建”和“开始”时间,您可以安排将来进行更改。

This design, as opposed to the two-table design, allows you to easily write queries that will automatically operate on the right data. 与双表设计相反,此设计允许您轻松编写将自动操作正确数据的查询。 Suppose your table is storing the tax rate over time... you don't want to have all your queries that use tax rates in their calculations have the extra complexity of deciding to look stuff up in a history table when processing old invoices, for example... you can just look up the tax rate in effect at the time the invoice was created in one query, regardless of whether it's the current tax rate or not. 假设您的表格随时间存储税率...您不希望在计算中使用税率的所有查询都具有在处理旧发票时决定在历史记录表中查找内容的额外复杂性,示例...您可以查询在一个查询中创建发票时生效的税率,无论它是否是当前税率。

This idea is not originally mine (although I did re-invent the rough idea on my own prior to reading about it)... you can find a detailed discussion of it in this online book . 这个想法本来不是我的(虽然我在阅读之前就自己重新发明了这个粗略的想法)......你可以在这本在线书中找到它的详细讨论。

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

I would also think about a database trigger on insert or update to record change details (who, when, what, value before, value after) to a separate audit table. 我还会考虑插入或更新时的数据库触发器,以将更改详细信息(who,when,what,value,value after)记录到单独的审计表中。 That way you know that even if the data is changed outide of your app using the database directly, it will still be picked up. 这样你就知道,即使你的应用程序使用数据库直接更改了数据,它仍然会被拾取。

You might also want to do something to detect if the data is changed outide of your app, such as calculate a hash or crc of the record and store it in a field somewhere, then check it when reading the data. 您可能还想要做一些事情来检测数据是否在您的应用程序中更改,例如计算记录的哈希值或crc并将其存储在某个字段中,然后在读取数据时进行检查。

I think your proposal would involve writing a lot of code/metadata to enable comparison of objects/records so you get a business-level audit. 我认为您的提案将涉及编写大量代码/元数据以实现对象/记录的比较,以便您进行业务级审计。

Alternatively, a database trigger may not give you a high-enough level view of what happened. 或者,数据库触发器可能无法为您提供足够高级别的视图。 This may be acceptable if you use the audit so infrequently that the effort of recreating the business meaning is ok. 如果您不经常使用审计来重新创建业务意义的努力是可以接受的,那么这可能是可以接受的。

This also seems like a good application for AOP (Aspects), where you could use reflection on the object model to dump something meaningful without requiring a lot of metadata. 对于AOP(Aspects)来说,这似乎也是一个很好的应用程序,您可以在对象模型上使用反射来转储有意义的内容而无需大量元数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM