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

时间:2009-12-23 13:48:54

标签: c# sql

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

所以更清楚:

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

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

  3. 使用示例如下:

    • 我有一篇新闻文章
    • 有人对该文章进行了一些更改
    • 主编看到此消息有一些拼写错误
    • 决定回滚到之前的有效版本(直到更新最新版本)

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

7 个答案:

答案 0 :(得分:14)

主表更改时存储更改的表称为审计表。您可以通过多种方式执行此操作:

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

还要记住,一个事务可以同时修改多个记录,因此你应该使用完整的修改记录集,而不仅仅是最后一个记录(正如大多数人迟迟意识到的那样)。

在触发器执行完成之前,控件不会返回到调用程序。因此,您应该尽可能快地保持代码。

  • 在中间层使用代码:此方法可以将更改保存到其他数据库,并可能会从数据库中卸载一些内容。但是,运行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

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

答案 1 :(得分:5)

您可以使用触发器。 这是one示例。

 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/

答案 2 :(得分:5)

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

MSDN - Auditing in SQL Server 2008

答案 3 :(得分:2)

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

例如,如果您有一个名为“book”的表,其中包含列“id”,“name”,“author”,则可以添加名为“book_version”的表,其中包含列“id”,“name”,“作者“,”version_date“,”version_user“

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

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

答案 4 :(得分:1)

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

答案 5 :(得分:0)

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

答案 6 :(得分:0)

我使用NHibernate.Enverse

解决了这个问题

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