保持数据库中数据更改的历史记录

数据库中某行中的每次数据更改都应将以前的行数据保存在某种历史记录中,以便用户可以回滚到上一行数据状态。 这种方法有什么好的做法吗? 尝试使用DataContract并对数据对象进行序列化和反序列化,但它对于复杂对象变得不那么混乱。

所以更清楚:

  1. 我正在使用NHibernate进行数据访问,并希望避免数据库依赖(对于使用SQL Server 2005进行测试)

  2. 我的目的是提供数据历史记录,以便每次用户都可以回滚到以前的某些版本。

使用示例如下:

  • 我有一篇新闻报道
  • 有人对那篇文章做了一些修改
  • 主编看到这个消息有一些错别字
  • 它决定回滚到以前的有效版本(直到更新最新版本)

我希望我能给你有效的信息。

在主表更改时存储更改的表称为审计表。 你可以这样做:

  • 在使用触发器的数据库中:我建议使用这种方法,因为如果没有记录,数据就无法改变。 执行此操作时,您必须考虑3种类型的更改:添加,删除,更新。 因此,您需要可在所有三个上运行的触发器function。

还要记住,事务可以同时修改多个记录,因此您应该使用完整的修改记录集,而不仅仅是最后一条记录(因为大多数人都迟到意识到他们这样做了)。

在触发器执行完成之前,控制不会返回到调用程序。 所以你应该保持代码尽可能轻快。

  • 在中间层使用代码:此方法将允许您将更改保存到不同的数据库,并可能从数据库中卸载一些负载。 但是,运行UPDATE语句的SQL程序员将完全绕过您的中间层,您将没有审计跟踪。

审计表的结构

您将拥有以下列:
Autonumber PK, TimeStamp, ActionType + All columns from your original table
我过去通过以下方式做到了这一点:

表结构:
Autonumber PK, TimeStamp, ActionType, TableName, OriginalTableStructureColumns

此结构意味着您为每个保存的数据表创建一个审计表。 数据保存和重建相当容易。 我会推荐这种方法。 名称值对:
Autonumber PK, TimeStamp, ActionType, TableName, PKColumns, ColumnName, OldValue, NewValue

此结构将允许您保存任何表,但您必须为触发器中的每个列创建名称值对。 这是非常通用的,但价格昂贵。 您还需要编写一些视图以通过取消数据重新创建实际行。 这变得乏味,通常不是遵循的方法。

Microsoft已在SQL Server 2008中引入了新的审计function。这篇文章描述了一些function和设计目标,这些function和设计目标可能对您选择的任何方法都有帮助。

MSDN – 在SQL Server 2008中进行审计

您可以使用触发器。 这是一个例子。

  AutoAudit is a SQL Server (2005, 2008) Code-Gen utility that creates Audit Trail Triggers with: * Created, Modified, and RowVerwsion (incrementing INT) columns to table * view to reconstruct deleted rows * UDF to reconstruct Row History * Schema Audit Trigger to track schema changes * Re-code-gens triggers when Alter Table changes the table 

http://autoaudit.codeplex.com/

保存序列化数据最终总是变得混乱,你是正确的,远离那个。 最好的办法是创建一个与主表具有相同列的并行“版本”表。

例如,如果你有一个名为“book”的表,列“id”,“name”,“author”,你可以添加一个名为“book_version”的表,列为“id”,“name”,“author”, “version_date”,“version_user”

每次在表“book”上插入或更新记录时,您的应用程序也会插入“book_version”。

根据您的数据库系统和数据库从应用程序访问的方式,您可以完全自动执行此操作(参见Doctr中的Versionable插件)

一种方法是使用支持这种本地的DB,如HBase 。 我通常不会建议“更改您的数据库服务器以获得这一function”,但由于您没有在您的问题中指定数据库服务器,我认为您的意思是开放式服务器,并且服务器中的本机支持是这个function的最佳实现之一。

你使用什么数据库系统? 如果您正在使用符合ACID(primefaces性,一致性,隔离,持久性)的数据库,那么您是否只能使用内置的回滚function返回上一个事务?

我使用NHibernate.Enverse解决了这个问题

对于那些有趣的内容,请阅读: http : //nhforge.org/blogs/nhibernate/archive/2010/07/05/nhibernate-auditing-v3-poor-man-s-envers.aspx