Sql server 维护跨多个表拆分的实体的审核日志

Sql server 维护跨多个表拆分的实体的审核日志,sql-server,triggers,history,logging,audit,Sql Server,Triggers,History,Logging,Audit,我们将一个实体拆分为5个不同的表。其中3个表中的记录是强制性的。其他两个表中的记录是可选的(基于实体的子类型) 其中一个表被指定为实体主表。其他四个表中的记录由master提供的唯一id进行键控 更新/删除触发器出现在每个表上后,记录的更改会将历史(从触发器内的已删除表)保存到相关的历史表中。每个历史记录表包含相关的实体字段+时间戳 因此,实时记录总是在实时表中,历史记录/更改总是在历史表中。可以根据时间戳列对历史记录进行排序。显然,时间戳列在历史记录表中是不相关的 现在,对于更困难的部分 记录

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

其中一个表被指定为实体主表。其他四个表中的记录由master提供的唯一id进行键控

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

因此,实时记录总是在实时表中,历史记录/更改总是在历史表中。可以根据时间戳列对历史记录进行排序。显然,时间戳列在历史记录表中是不相关的

现在,对于更困难的部分

  • 记录最初插入到单个事务中。在一次交易中将写入3条或5条记录
  • 5个表中的任何一个或所有表都可能发生单独的更新
  • 所有记录都作为单个事务的一部分进行更新。同样,3或5条记录将在单个事务中更新
  • 数字2可以重复多次
  • 数字3可以重复多次
  • 应用程序应仅根据作为单个事务写入的记录显示时间点历史记录条目列表(仅限第1、3和5点)

    我目前有一个算法存在问题,该算法仅基于时间戳数据检索历史记录

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


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

    您的HistoryMaster似乎与我们在一个系统中处理多个相关项的历史记录的方式相似。通过在历史记录表中使用一个点来挂起所有相关更改,很容易创建一个将历史记录母版用作中心并附加相关信息的视图。它还允许您不在历史记录中创建不需要审核的记录

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

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


    请注意,使用审核/主表的优势在于,与源表相比,您对历史记录表所做的更改非常少:一次审核(在我们的示例中,一个Guid,尽管在非分布式数据库中自动编号可以)。

    您是否可以向实体主表添加时间戳/RowVersion数据类型列,并将所有审计记录与之关联

    但对任何“子”表的更新都需要更新主实体表,以强制更改时间戳/行版本:(

    或者在其中粘贴一个GUID,以便在相关记录发生更改时刷新该GUID


    想一想,大声说出来,让一个表以1:1的比例连接到主实体,它只包含主实体ID和记录的“版本号”——时间戳/RowVersion、GUID、递增的数字或其他内容。

    我认为这是试图捕获“抽象”的症状在应用程序堆栈的最低级别(数据库)审核事件

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


    我知道您问过如何在DB触发器中执行此操作。我不知道SQL Server,但在Oracle中,您可以通过使用DBMS\u事务.LOCAL\u事务\u ID系统包返回当前事务的ID来克服此问题。如果您可以检索等效的SQL Server值,那么您可以使用它来绑定t他将当前事务的更新一起记录到一个逻辑包中。

    历史记录表中的“时间点历史可以检索…按时间戳排序”行的更改速度可能快于datetime的粒度(我认为是3ms)因此,我们还有一个EditNumber列,它由UPDATE触发器递增,正如其他人所说,“version”可以绑定子历史记录