是否有在数据库中维护历史记录的最佳实践?

时间:2010-05-20 15:26:12

标签: database-design

我不经常做数据库工作,所以这对我来说是完全不熟悉的领域。

我有一个表,其中包含一组用户可以更新的记录。但是,我现在想要保留其更改的历史记录,以防他们想要回滚。在这种情况下,回滚不是数据库回滚,而是更像是两周后当他们意识到他们犯了错误时还原更改。区别在于我无法完成交易。

当前的做法是使用单独的表,还是仅使用当前表中的标志?

这是一个小型数据库,每个表有5个表< 6列,<共计1000行。

6 个答案:

答案 0 :(得分:12)

从这个问题

How to keep history of record updates in MySQL?

保持版本历史记录的一种简单方法是创建基本相同的表(例如,使用_version后缀)。这两个表都有一个版本字段,对于主表,您为每次更新都会增加。版本表将具有复合主键(id,version)。

每当您对实际表进行更新时,您还会在版本表中插入包含重复数据的新行。每当您想要查找版本历史记录时,您需要做的就是SELECT * FROM content_version WHERE id = CONTENT_ID ORDER BY version。

如果您使用Doctrine ORM之类的东西,它会有一种行为,可以通过事件侦听器自动执行此操作。您可以在此处查看:http://www.doctrine-project.org/documentation/manual/1_2/en/behaviors#core-behaviors:versionable

OR

最简单的解决方案(取决于您的特定需求)可能是为您的表添加更新/插入/删除触发器,因此您可以在插入/更新/删除数据时执行额外的日志记录。这样就可以覆盖对数据库的人工干预......

查看http://dev.mysql.com/doc/refman/5.1/en/triggers.html了解详情。

答案 1 :(得分:1)

您可以使用时间戳来指示创建记录的时间,并使用状态指示器来指示记录是否为“有效”。

当他们对记录进行更新时,将其副本作为新记录插入(触发器可以使时间戳保持最新),然后将旧记录状态设置为“存档”,将新记录状态设置为“活动”。如果需要,还可以使用其他审核字段,例如“上次更新时间戳”,“日期存档”,“日期未归档”(用于回滚时),“由用户创建”,“用户上次修改时间”,...如果您想要完整的审计历史记录,则需要一个单独的审计表。

回滚只是选择一个版本并将其标记为“活动”而将其他版本标记为“存档”。

还有其他方案更灵活但也更复杂,但您可能不需要它们。

答案 2 :(得分:1)

一个选项是让所有表包含ID列和VersionNo列。然后,不是运行UPDATES,而是插入一个具有相同ID和增加版本号的新记录。

然后,您可以为每个表创建一些视图,这些视图仅返回每个ID的最新版本,以使您的查询更易于管理。

答案 3 :(得分:1)

沮丧的答案是一个解决方案 - 另一个是审计表,记录变更,时间和人员。这真的是一个问题的方法。如果应用程序表上的性能至关重要,并且它们可以使用“活动行”方法大量增长,那么审计表会更好,因为它会将历史记录与活动内容分开(我希望修复用户错误的次数更少)比“正常”交易更常见。

答案 4 :(得分:1)

我会推荐第二张桌子。一种超级简单易用的方法是复制每个表的模式和日期/时间戳列以及将存储原始数据的“ModifiedByUserID”列。

或者,如果用户一次不修改同一行中的大量记录,则可以通过制作下面的架构来节省空间并更好地了解正在发生的事情:

ChangesTable

ChangeID 
[TABLE UNIQUE ID] 
UserName 
Field 
OldValue
NewValue 
CreatedDate

答案 5 :(得分:0)

这种方法怎么样我有一个关系数据库,有一些表和构建记录,在“堆栈”上有一个时间戳。

例如:假设我创建了employee table + Car table,在第三个表格中,我会在每次更改时记录关系employee <-> car(带有日期)。当然,这应该由GUI支持,我可以从中选择将填充新表的记录的组件(员工和汽车):

first record employee1 <-> car1 : 01/01/2013
then         employee1  <-> car2: 01/06/2013

如果我想了解历史,我只想问这张桌子。无需更新历史记录随更改所做的任何事情。