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

发布于 2024-07-16 10:51:33 字数 234 浏览 8 评论 0原文

我正在尝试创建一些功能,以保留给定用户表单中的数据如何随时间变化的审计跟踪,并在该页面的底部提供日期审计。 例如:

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

我这样做的方法是将数据以其当前格式存储在会话中,然后在保存时检查所存储的数据是否存在任何差异。 如果有,我会将最新编辑之前的数据存储在名为历史记录的表中,并将新值存储在当前用户表中。

这是最好的方法吗?

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".

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.

Is this the best approach to be taking?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

梦忆晨望 2024-07-23 10:51:33

我不确定是否存在一种“最佳方法”,需要考虑很多变量,包括您的发展道路有多远。

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

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

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. Not impossible, but more work and several ways to approach this (db user executing query, common user column in each table, etc.)
  • 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. 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, i.e. store audit event date in UTC as well as including the timezone offset.
  • 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 :)
一瞬间的火花 2024-07-23 10:51:33

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

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.

往事随风而去 2024-07-23 10:51:33

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

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

这个想法最初不是我的(尽管在阅读它之前我确实重新发明了我自己的粗略想法)......您可以在这个 在线图书

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. "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. 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.

动听の歌 2024-07-23 10:51:33

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

The session involvement makes me a little wary (are you sure you're handling it properly when two users are working on the same data at the same time?), but in general, yeah, keeping a history table is the right thing.

琉璃繁缕 2024-07-23 10:51:33

我还会考虑插入或更新时的数据库触发器,以将更改详细信息(谁、何时、什么、之前的值、之后的值)记录到单独的审计表中。 这样您就知道,即使直接使用数据库在应用程序外部更改数据,它仍然会被拾取。

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

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. 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.

×纯※雪 2024-07-23 10:51:33

我认为您的建议将涉及编写大量代码/元数据来比较对象/记录,以便您获得业务级审计。

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

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文