【问题标题】:Database structure to track change history跟踪更改历史的数据库结构
【发布时间】:2010-09-13 14:03:49
【问题描述】:

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

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

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

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

【问题讨论】:

    标签: ruby-on-rails database-design


    【解决方案1】:

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

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

    根据您的设计,您可能不想使用“表”和“列”,而是使用“对象”和“属性”等。

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

    编辑:一些人正确地指出,使用此解决方案您无法将变更集整合在一起。我在上面的表格中忘记了这一点——我使用的实现还有一个“事务”表,其中包含日期时间、用户和其他信息,以及一个“事务 ID”列,所以设计看起来像这样:

    CHANGE LOG TABLE:
    RecordID  Table  Column  OldValue  NewValue  TransactionID
    --------  -----  ------  --------  --------  -------------
    
    TRANSACTION LOG TABLE:
    TransactionID  UserID  TransactionDate
    -------------  ------  ---------------
    

    【讨论】:

    • 感谢您的回答。唯一的问题是我如何将更改分组到一个更改集中?
    • 您能否给出一些查询或应用程序代码示例,您将使用这些示例来构建基于此记录更改表的历史记录?您将如何提取特定修订版?
    • 有什么聪明的方法可以在这里获取OldValue,还是我只需要为每次更改查询它?
    【解决方案2】:

    你在追求这样的数据库机制吗?

       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
    

    【讨论】:

    • 并非如此。我只是在看如何存储数据。不是如何将数据放入表中。
    • 将数据放入表在功能上与存储数据相同。那么你真正想要做什么呢?
    • 在工作中我们使用非常相似的东西,我们使用表“历史”对每个表进行修改,因此我们保留受影响表的名称、受影响行的 PK 和什么操作它是(插入、删除、更新)。在相关子表中,所有列的名称、先前值和新值。
    【解决方案3】:

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

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

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

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

    这是我的表结构:

    +------------------+           +------------------+
    | LoggableEntity   |           | EntityLog        |
    | ---------------- |           | ---------------- |
    | (PK) ID          | <--+      | (PK) ID          |
    +------------------+    +----- | (FK) LoggableID  |
            ^                      |      ...         |
            |                      +------------------+
    +------------------+
    | Customer         |
    | ---------------- |
    | (PK) ID          |
    | (FK) LoggableID  |
    |      ...         |
    +------------------+
    

    【讨论】:

    • 你有没有使用工具制作架构图?
    • 这取决于你在说什么。当我做某事时,我通常使用 SparX Enterprise Architect (sparxsystems.com/products/ea/index.html)。但是,如果您打算为这篇文章创建架构图,那么不会。只是纯ASCII。 :-(
    【解决方案4】:

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

    这是我见过的一种解决方案,尽管我不确定它是否是最好的。有一个主键,比如id,它指向一个特定的版本。还有ticket_numberrevision_date 字段。 ticket_number 在您修改工单时不会更改,但 idrevision_date 会更改。然后,根据上下文,您可以使用groupwise max 获取特定修订版或特定票证的最新修订版。

    【讨论】:

    • 我以前见过。当您只查看一个版本或比较两个版本时,它可能非常适合 wiki。出于我的目的,需要更多的代码才能在一个大视图中查看哪些事情发生了变化。
    【解决方案5】:

    我会说创建某种事件侦听类,每次系统内发生某些事情时您都可以 ping 并在数据库中放置对该事件的描述。

    它应该存储基本的 who/what/where/when/what 信息。

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

    【讨论】:

    • 数据库结构是什么样的?
    【解决方案6】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-03-17
      • 2013-11-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多