创建应用程序数据的快照 – 最佳实践

我们有一个使用.NET FW 4.0在C#中开发的文本处理应用程序,其中管理员可以定义各种设置。 所有这些“设置”数据都驻留在大约50个具有外键关系和Identity主键的表中(我认为这会使它变得棘手)。 整个数据库不超过100K记录,平均表有大约6个短列。 该系统基于MS SQL 2008 R2 Express数据库。

我们需要创建所有这些数据的快照,以便系统管理员可以随时回滚到其中一个快照。 我们只需要保留最后5个快照。 必须从应用程序GUI开始创建快照,因此必要时必须回滚到任何快照(由于拒绝直接访问数据库,因此不允许使用SSMS)。 系统仍在开发中(我们真的完成了吗?)这意味着新表和列会多次添加。 因此,我们需要一个可以自动处理更改的强大方法(在插入/更改列之后挖掘代码是我们想要避免的,除非没有其他方法)。 最好的方法是告诉“我想创建名称以’Admin’开头的所有表的快照”。 显然,这是一项数据库密集型任务,但由于它仅在紧急情况下使用,这是我不介意的事情。 我也不介意是否发生表锁,因为在创建或回滚快照的过程中,没有人会尝试使用这些表。

问题可分为两部分:

  1. 创建快照
  2. 回滚到快照

关于问题#1。 我们可能有两种选择:

  1. 将数据导出为XML(文件或数据库列)
  2. 将SQL中的数据复制到相同或不同的表中(例如,再次使用与前缀为“Backup”的原始表相同的名称创建相同的表结构)。

关于问题#2。 我看到的最大问题是如何将所有数据重新导入到外键关联表中,这些表使用IDENTITY列进行PK生成。 我需要删除所有受影响的表中的所有数据,然后重新导入所有数据,同时暂时放宽FK约束并关闭身份生成。 加载数据后,我应检查FK约束是否仍然正常。

或许我应该找到一种加载表的逻辑方式,以便在加载时可以保留约束检查(因为我们没有无法管理的表数,这可能是一个可行的解决方案)。 当然,出于显而易见的原因,我需要在单个事务中进行所有删除和重新加载。

我怀疑可能没有基于SQL的纯解决方案,尽管SQL CLR可能有助于避免将数据移出SQL Server。

我们面临同样的问题吗? 也许有人成功解决了这样的问题?

我不指望一步一步的指导。 任何有关从何处开始,获取哪些路径(导出到RAW XML或在数据库中保存快照或两者)的帮助,优点/缺点都非常有用。

谢谢你的帮助和时间。

丹尼尔

按日期范围进行的一种版本控制是企业应用程序中记录的常用方法。 作为一个例子,我们有一个商业实体(我们)或公司(英国)的表格,我们将当前的官方名称保存在另一个表格中,如下所示:

CompanyID Name ValidFrom ValidTo 12 Business Lld 2000-01-01 2008-09-23 12 Business Inc 2008-09-23 NULL 

最后一条记录中的null表示这是当前记录。 您可以使用上述逻辑并可能添加更多列以获得更多控制。 这种方式没有重复,您可以将历史记录保持在任何级别,并轻松地在表之间同步当前值。 最后表现会很棒。

我们没有这个确切的问题,但我们有一个非常类似的问题,我们为客户提供一组基准的配置数据(相当复杂,主要是身份PK),当我们提供新版本时需要更新。

我们的机制可能对你的情况有些过分,但我确信它的一部分是适用的。

基本方法是这样的:

首先,我们执行一个脚本,该脚本删除所有FK约束,并将当前为非NULL的那些FK列的可为空性更改为NULL。 此脚本还会删除所有触发器,以确保不会执行其中实现的任何逻辑约束。

接下来,我们执行数据导入,在更新表之前设置identity_insert,然后在更新表中的数据后重新设置它。

接下来,我们执行一个脚本,该脚本检查新添加的项目相对于外键的数据完整性。 在我们的例子中,我们知道可以安全地删除没有相应父记录的项目,但您可以选择采用不同的方法(报告错误并让某人手动处理该问题)。

最后,一旦我们validation了数据,我们就会执行另一个恢复可空性的脚本,添加FK并重新安装触发器。

如果您有预算,我强烈建议您查看Red Gate提供的工具,特别是SQL Packager和SQL Data Compare(我怀疑可能还有其他工具,我们只是不对他们有任何经验)。 这些工具对于我们战略的成功实施至关重要。

更新

我们通过RedGate的SQL Packager生成的SQL脚本提供基线配置。

因为我们的最终用户可以在更新之间修改数据库,这将导致我们的数据库中的身份值不同,我们实际上将基准主键和外键存储在每个记录中的不同字段中。

当我们更新客户数据库并且我们需要将新记录链接到已知配置信息时,我们可以使用基线字段来找出特定于数据库的FK应该是什么。

换句话说,对于众所周知的配置记录,始终存在一组已知的字段ID,无论数据库中是否修改了其他数据,我们都可以使用它来将记录链接在一起。

例如,如果我将Table1链接到Table2,则Table1将具有基线PK,而Table2将具有基线PK和包含Table1的基线PK的基线FKey。 当我们更新记录时,如果我们添加一个新的Table2记录,我们所要做的就是找到具有指定基线PK的Table1记录,然后使用Table1中的实际PK更新Table2中的实际FKey。