数据库 - 数据版本控制

时间:2009-04-17 22:12:12

标签: database database-design versioning

关于在数据库中对数据进行版本控制,我已经阅读了关于SO的一些问题(例如this one)。

我喜欢上面提到的一些建议。我有最长的时间想要(需要)修改我的许多桌子,但从来没有绕过它。作为一个只有简单的数据库工作的程序员,我想知道如何才能实现这一目标。

我不是要求SQL语法中的实际解决方案。我最终可以为自己解决这个问题(或者在时机成熟时发布)。我只是要求人们评论他们将如何进行评论以及如果我要“修改”数亿条记录,可能会出现任何潜在的性能问题。或者任何其他建议,只要它基于以下示例。

举个简单的例子:

Person
------------------------------------------------
ID                UINT NOT NULL,
PersonID          UINT NOT NULL,
Name              VARCHAR(200) NOT NULL,
DOB               DATE NOT NULL,
Email             VARCHAR(100) NOT NULL

Audit
------------------------------------------------
ID                UINT NOT NULL,
UserID            UINT NOT NULL,               -- Who
TableName         VARCHAR(50) NOT NULL,        -- What
OldRecID          UINT NOT NULL,               -- Where
NewRecID          UINT NOT NULL,
AffectedOn        DATE NOT NULL,               -- When
Comment           VARCHAR(500) NOT NULL        -- Why

如果TableName是字符串,我不确定如何将Audit表链接到任何其他表(例如Person)?

另外,假设我有三个GUI来填充:

  1. 特定人员ID的完整记录
  2. 列出所有人(按身份证)
  3. 的表格视图
  4. 一个视图,显示每个人在每个条目下面的修订信息(每人的修订数量,修订日期,修订评论等),按最新版本排序。
  5. 要完成1和2,查询Person表或Audit表会更好吗?

    要完成3,所谓的数据库专家是否只需获取所有记录并将其传递给软件进行处理,或按PersonID和受影响日期分组?这通常是在一个查询中处理还是多次处理?

4 个答案:

答案 0 :(得分:46)

多年来我已经完成了各种审计计划,目前我正在实施这样的计划:

Person
------------------------------------------------
ID                UINT NOT NULL,
PersonID          UINT NOT NULL,
Name              VARCHAR(200) NOT NULL,
DOB               DATE NOT NULL,
Email             VARCHAR(100) NOT NULL


Person_History
------------------------------------------------
ID                UINT NOT NULL,
PersonID          UINT NOT NULL,
Name              VARCHAR(200) NOT NULL,
DOB               DATE NOT NULL,
Email             VARCHAR(100) NOT NULL
AuditID           UINT NOT NULL


Audit
------------------------------------------------
ID                UINT NOT NULL,
UserID            UINT NOT NULL,               -- Who
AffectedOn        DATE NOT NULL,               -- When
Comment           VARCHAR(500) NOT NULL        -- Why

当前记录始终位于Person表中。如果有更改,则会创建审计记录,并将旧记录复制到Person_History表中(请注意,ID不会更改,并且可能有多个版本)

审核ID位于* _History表中,因此您可以根据需要将多个记录更改链接到一个审核记录。

编辑:
如果每个基表没有单独的历史记录表,并且想要使用同一个表来保存旧的和“已删除”记录,则必须使用状态标记标记记录。问题是查询当前记录时真的很痛苦 - 相信我,我已经做到了。

答案 1 :(得分:6)

如何正常创建表,在每条记录上都有一个ModifiedDate Colm(如果你愿意,还有ModifiedBy),并通过物化视图进行所有数据访问,该视图按Id对数据进行分组,然后进行HAVING ModifiedDate = MAX(ModifiedDate)?

这样,添加具有相同Id的新记录将从视图中删除旧记录。如果要查询历史记录,请不要查看视图

我总是发现使用相同的Colm维护不同的表是复杂且容易出错的。

答案 2 :(得分:2)

在DJ的帖子中使用每个基表的历史表和Karl关于可能的性能问题的评论后,我做了一些SQL研究,以便找出从一个表到一个表的最快转移方式另一个。

我只想记录我发现的内容:

我认为我必须进行SQL提取以从基表加载记录,然后进行SQL推送以将记录放入历史表中,然后更新基表以插入更改的数据。共3笔交易。

但令我惊讶的是,我意识到您可以使用SELECT INTO语法使用一个SQL语句执行前两个事务。我认为这样做的速度会快一百倍。

然后,这将使我们只需使用基表中的新数据更新记录。

我仍然没有找到一个SQL语句一次完成所有3个事务(我怀疑我会)。

答案 3 :(得分:1)

我喜欢你的审计表,这是一个好的开始。您的审计表存在基数问题,因此我将其作为两个表格填写:

Person
------------------------------------------------
ID                UINT NOT NULL,
PersonID          UINT NOT NULL,
Name              VARCHAR(200) NOT NULL,
DOB               DATE NOT NULL,
Email             VARCHAR(100) NOT NULL,
AuditID           UINT NOT NULL 

Audit
------------------------------------------------
ID                UINT NOT NULL,
TableName         VARCHAR(50) NOT NULL,        -- What
TableKey          UINT NOT NULL,
CreateDate        DATETIME NOT NULL  DEFAULT(NOW),
CreateUserID      UINT NOT NULL,
ChangeDate        DATETIME NOT NULL  DEFAULT(NOW),
ChangeUserID      UINT NOT NULL

Audit_Item
------------------------------------------------
ID                UINT NOT NULL,
AuditID           UINT NOT NULL,               -- Which audit record
UserID            UINT NOT NULL,               -- Who
OldRecID          UINT NOT NULL,               -- Where
NewRecID          UINT NOT NULL,
AffectedOn        DATE NOT NULL,               -- When
Comment           VARCHAR(500) NOT NULL        -- Why

建议的初始布局有一条审核记录,指向(我假设)两条人员记录。这种设计的挑战是:

  • 您人员表中的哪些记录 目前的“真实”记录是什么?
  • 您如何代表整个历史 对人员记录的更改?如果 你指的是两个记录 Person表,然后看点#1: 哪一个是目前的记录?
  • 汇总了Create *,Change *字段 来自Audit_Item的集合 记录。他们只是为了 四通八达的交通网络。
  • Person表中的AuditID键允许您指向 回到Audit表并转到 个人的历史 无需查询审计 带有WHERE TableName='Person'
  • 条款的表格