跟踪更改历史记录的数据库结构

问题描述 投票:0回答:6

我正在为项目管理系统作为个人项目进行数据库设计,但我遇到了障碍。

我想实现一个票证系统,并且我希望票证看起来像 Trac 中的票证。我将使用什么结构来复制这个系统? (我还没有在我的任何系统上成功安装 trac,所以我真的看不到它在做什么)

注意:我对尝试存储或显示任何版本的票证都不感兴趣。我只需要变化的历史。我不想存储额外的数据。此外,我还使用文本字段中的序列化数组实现了类似的功能。我不想再次将其作为解决方案来实施。

编辑:我只寻找数据库结构。触发器/回调并不是真正的问题。

ruby-on-rails database-design
6个回答
18
投票

我使用“瘦”设计实现了纯记录更改数据:

RecordID  Table  Column  OldValue  NewValue
--------  -----  ------  --------  --------

您可能不想使用“表”和“列”,而是使用“对象”和“属性”等等,具体取决于您的设计。

这具有灵活性和简单性的优点,但代价是查询速度——“表”和“列”列上的聚集索引可以加快查询和过滤速度。但是,如果您要经常在表或对象级别在线查看更改日志,您可能需要设计更扁平的东西。

编辑:有几个人正确地指出,使用此解决方案您无法整合变更集。我在上表中忘记了这一点——我使用的实现还有一个包含日期时间、用户和其他信息的“Transaction”表,以及一个“TransactionID”列,因此设计如下所示:

CHANGE LOG TABLE:
RecordID  Table  Column  OldValue  NewValue  TransactionID
--------  -----  ------  --------  --------  -------------

TRANSACTION LOG TABLE:
TransactionID  UserID  TransactionDate
-------------  ------  ---------------

3
投票

您想要这样的数据库机制吗?

   CREATE OR REPLACE TRIGGER history$yourTable
        BEFORE UPDATE ON yourTable
        FOR EACH ROW
        BEGIN
            INSERT INTO
                history
            VALUES
                (
                :old.field1,
                :old.field2,
                :old.field3,
                :old.field4,
                :old.field5,
                :old.field6
                );
        END;
    /
    SHOW ERRORS TRIGGER history$yourTable

3
投票

我做了这样的事情。我有一个名为 LoggableEntity 的表,其中包含:ID (PK)。

然后我有 EntityLog 表,其中包含有关对可记录实体(记录)进行的更改的信息:ID(PK)、EntityID(FK 到 LoggableEntity.ID)、ChangedBy(进行更改的用户名)、ChangedAt(更改发生时的小日期时间) 、类型(枚举:创建、删除、更新)、详细信息(包含已更改内容的备注字段 - 可能是带有序列化详细信息的 XML)。

现在我想要跟踪的每个表(实体)都是从 LoggableEntity 表“派生”的 - 这意味着例如客户具有 LoggableEntity 表的 FK。

现在,每当客户记录发生更改时,我的 DAL 代码都会负责填充 EntityLog 表。每次当它看到实体类是可记录实体时,它都会将新的更改记录添加到实体日志表中。

这是我的表格结构:

┌──────────────────┐           ┌──────────────────┐
│ LoggableEntity   │           │ EntityLog        │
│ ──────────────── │           │ ──────────────── │
│ (PK) ID          │ ◀──┐      │ (PK) ID          │
└──────────────────┘    └───── │ (FK) LoggableID  │
        ▲                      │      ...         │
        │                      └──────────────────┘
┌──────────────────┐
│ Customer         │
│ ──────────────── │
│ (PK) ID          │
│ (FK) LoggableID  │
│      ...         │
└──────────────────┘

2
投票

就不存储大量额外数据而言,我想不出任何好的方法来做到这一点。您必须存储每个修订才能看到更改。

这是我见过的一种解决方案,尽管我不确定它是否是最好的解决方案。有一个主键,例如

id
,它指向特定的修订版。还有
ticket_number
revision_date
字段。当您修改工单时,
ticket_number
不会更改,但
id
revision_date
会更改。然后,根据上下文,您可以使用 groupwise max 获取特定修订版或特定工单的最新修订版。


1
投票

我想说创建某种事件监听类,每次系统中发生某些事情时都会对其进行 ping 操作,并将事件的描述放入数据库中。

它应该存储基本的人物/内容/地点/时间/内容信息。

对项目事件表进行排序应该可以得到你想要的信息。


0
投票

一种可能的解决方案是将票证的副本与进行更改的用户一起存储在历史表中。

但是,这将存储大量额外数据,并且需要大量处理来创建 Trac 显示的视图。

© www.soinside.com 2019 - 2024. All rights reserved.