维护跨多个表分割的实体的审核日志

时间:2009-01-19 11:05:13

标签: sql-server triggers history logging audit

我们有一个实体分为5个不同的表。其中3个表中的记录是强制性的。其他两个表中的记录是可选的(基于实体的子类型)。

其中一个表被指定为实体主数据。其他四个表中的记录由来自master的唯一ID键入。

在每个表上存在更新/删除触发器之后,记录的更改将历史记录(从触发器中的已删除表)保存到相关历史记录表中。每个历史记录表包含相关的实体字段+时间戳。

因此,实时记录始终位于实时表中,历史/更改位于历史表中。可以根据时间戳列对历史记录进行排序。显然,时间戳列与历史表之间没有关系。

现在,对于更困难的部分。

  1. 记录最初插入单个交易中。在一次交易中将写入3或5条记录。
  2. 5个表中的任何一个或全部都可以进行单独更新。
  3. 所有记录都作为单个交易的一部分进行更新。同样,3或5条记录将在一次交易中更新。
  4. 数字2可以重复多次。
  5. 3号可以重复多次。
  6. 应用程序应显示基于仅作为单个交易记录的记录的时间点历史记录条目列表(仅限点1,3和5)

    我目前遇到一种算法问题,该算法将仅根据时间戳数据检索历史记录。

    添加HISTORYMASTER表来保存有关事务的额外信息似乎可以部分解决问题。在每笔交易之前,新记录将添加到HISTORYMASTER中。在事务期间,新的HISTORYMASTER.ID将保存到每个实体表中。 通过选择特定HISTORYMASTER.ID的第一条记录(按时间戳排序),可以检索时间点历史记录

    对于跨越多个表的实体,是否有更优化的方法来管理基于AFTER(UPDATE,DELETE)TRIGGER的审计表?

3 个答案:

答案 0 :(得分:1)

您的HistoryMaster似乎与我们在其中一个系统中处理多个相关项目的历史记录类似。通过使用单点挂起历史表中的所有相关更改,可以轻松创建一个使用历史主服务器作为集线器并附加相关信息的视图。它还允许您在历史中创建不需要审核的记录。

在我们的例子中,主表称为EntityAudit(其中实体是保留的“主要”项目),所有数据都存储在与Audit相关的EntityHistory表中。在我们的例子中,我们使用数据层来处理业务规则,因此很容易将审计规则插入到数据层本身。我觉得数据层是这种跟踪的最佳点,当且仅当所有修改都使用该数据层时。如果您有多个应用程序使用不同的数据层(或根本没有),那么我怀疑触发器创建主记录几乎是唯一的方法。

如果您没有在审核中跟踪其他信息(我们跟踪进行更改的用户,例如,主表上没有的内容)那么我会考虑额外的审核“主要”记录本身的ID。您的描述似乎并不表示您对单个表的微小更改感兴趣,而只是对更新整个实体集的更改感兴趣(尽管我可能会错过阅读)。如果你不关心小编辑,我只会这样做。在我们的例子中,我们需要跟踪所有更改,甚至跟踪相关记录。

请注意,使用Audit / Master表的优势在于,与源表相比,您对History表进行了最小更改:单个AuditID(在我们的示例中为a) Guid,虽然自动编号在非分布式数据库中没问题。)

答案 1 :(得分:0)

您可以将TimeStamp / RowVersion数据类型列添加到实体主表,并将所有审核记录与该关联吗?

但任何“子”表的更新都需要更新主实体表以强制更改TimeStamp / RowVersion:(

或者在那里粘贴一个GUID,只要其中一个相关记录发生变化,你就会刷新。

认为通过大声地将一个表加入1:1的表可能会更好,主表实体只包含主实体ID和记录的“版本号” - TimeSTamp / RowVersion,GUID,递增数字,或其他。

答案 2 :(得分:0)

我认为这是尝试在应用程序堆栈的最低级别捕获“抽象”审计事件的一种症状 - 数据库。

如果可以考虑在业务层中捕获审核事件。这将允许您捕获每个逻辑事务的历史记录而不是逐行记录。日期/时间对于解决这样的事情是不可靠的,因为它对于不同的行可能是不同的,对于并发(或间隔很小的)事务也是如此。

我知道您已经在DB触发器中询问过如何执行此操作。我不了解SQL Server,但在Oracle中,您可以通过使用 DBMS_TRANSACTION.LOCAL_TRANSACTION_ID 系统包来返回当前事务的ID。如果可以检索等效的SQLServer值,则可以使用此值将当前事务的记录更新绑定到逻辑包中。