3

We have an entity split across 5 different tables. Records in 3 of those tables are mandatory. Records in the other two tables are optional (based on sub-type of entity).

One of the tables is designated the entity master. Records in the other four tables are keyed by the unique id from master.

After update/delete trigger is present on each table and a change of a record saves off history (from deleted table inside trigger) into a related history table. Each history table contains related entity fields + a timestamp.

So, live records are always in the live tables and history/changes are in history tables. Historical records can be ordered based on the timestamp column. Obviously, timestamp columns are not related across history tables.

Now, for the more difficult part.

  1. Records are initially inserted in a single transaction. Either 3 or 5 records will be written in a single transaction.
  2. Individual updates can happen to any or all of the 5 tables.
  3. All records are updated as part of a single transaction. Again, either 3 or 5 records will be updated in a single transaction.
  4. Number 2 can be repeated multiple times.
  5. Number 3 can be repeated multiple times.

The application is supposed to display a list of point in time history entries based on records written as single transactions only (points 1,3 and 5 only)

I'm currently having problems with an algorithm that will retrieve historical records based on timestamp data alone.

Adding a HISTORYMASTER table to hold the extra information about transactions seems to partially address the problem. A new record is added into HISTORYMASTER before every transaction. New HISTORYMASTER.ID is saved into each entity table during a transaction. Point in time history can be retrieved by selecting the first record for a particular HISTORYMASTER.ID (ordered by timestamp)

Is there any more optimal way to manage audit tables based on AFTER (UPDATE, DELETE) TRIGGERs for entities spanning multiple tables?

4

3 回答 3

1

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

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

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

请注意,使用 Audit/Master 表的优势在于,与源表相比,您对 History 表所做的更改最少:单个 AuditID(在我们的示例中为 Guid,尽管自动编号在非分布式数据库)。

于 2009-01-26T16:47:08.357 回答
0

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

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

或者在其中粘贴一个 GUID,只要相关记录之一发生更改,您就可以对其进行更新。

通过大声思考,最好将一个表以 1:1 的比例连接到主实体,该表仅包含主实体 ID 和记录的“版本号”——TimeSTamp / RowVersion、GUI​​D、递增的数字,或别的东西。

于 2009-02-15T23:35:06.390 回答
0

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

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

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

于 2009-02-26T06:29:02.817 回答