我有一个针对 sqlserver DB 运行的 n 层 winform 客户端服务器应用程序。我希望它有时能够“离线”运行(未连接到数据库)并在重新连接时重新调整对主数据库的更改。现在,我要做出艰难的架构决定:我应该使用数据库复制还是使用队列/脚本等自己管理它。我的应用程序很复杂 - 我使用包含自动增量键和表之间的外键约束的表的数据库。我的部分数据没有像图片和文档那样嵌入到数据库中。非常想听听您的意见和过去的经验!谢谢,阿迪
5 回答
(免责声明:我假设您已经考虑过使用 .NET 数据集并打折它们,因为它们旨在帮助解决您所描述的问题域。)
我曾经在一家为其全国连锁店开发销售点系统的公司工作。主数据库存储在总部,而每个商店都有自己的数据库缩减版本存储在该站点的本地。实际上,每个商店都一直处于离线状态,因此与您描述的情况不太一样,但是我们必须处理一些我认为您需要处理的同步/复制问题。
我们每天晚上都进行数据通信:商店将在预定时间连接到总部,上传数据更改包,然后下载要应用于该商店本地数据库的类似数据更改包。然后,我们在两个站点(总部和商店)都有您可能称之为“数据同步引擎”的东西,它将处理这些数据包,将更改(插入/更新/删除)折叠回相关数据库。
当您像这样执行基本数据复制时,正如 Sergio 所提到的,存在许多潜在的陷阱。一个是身份,即如何派生唯一标识表行的主键。另一个是版本控制,以及如何处理同一行的不同版本之间的冲突。
在我们的例子中,我们通过使用 GUID 作为主键而不是使用自动递增列来让事情变得简单(-ier!)。使用 GUID 并非没有问题,但在我们的案例中,这意味着我们可以将主键分配给新的数据行,而不必担心其他人使用它。
我对我们如何处理版本控制问题有点模糊(已经有几年了!),但从记忆中我认为我们在每个表行上有两个时间戳:其中一个记录了行更新时的日期/时间总公司; 另一个,当它在商店更新时。每行还有两个“版本号”,表示总部和商店的行版本。数据协调涉及将这些时间戳和版本号相互比较,最近的更改“获胜”(当然假设对方没有更改行)。
正如 Sergio 所指出的,您最大的问题将是处理数据协调冲突。在我们的案例中,这发生在商店和总部在同一天更改相同的数据项时。我们通过始终在商店结束更改失败并在总部编写自定义数据协调应用程序来解决此问题,这涉及到用户直观地比较和合并数据项的两个冲突版本。从理论上讲,我认为您可以使用一些自定义处理规则自动合并不同版本,但是您需要权衡开发类似内容的成本与发生冲突的可能性。从记忆来看,这对我们的系统来说从来没有成为一个大问题,尽管有大量商店(几百家)对同一组数据进行了更改。当然是 YMMV。
您应该查看Microsoft Sync Framework。
从头开始自己构建偶尔离线的解决方案是一项复杂的工作。在我的职业生涯中,我见过很多优秀的开发团队把它搞砸了。我并不是说你自己构建它会有问题,但为什么不使用已经存在的东西呢?如果您发现它不能满足您的需求,您可能会对如何编写自己的解决方案有更好的理解。
权衡是您必须学习同步框架,但有些示例您可能可以立即利用。
我以前从来没有做过这样的事情,但在我看来,如果你这样做,你可能会遇到严重的问题......
从技术上讲,我认为实施起来并不难。基本上,每次客户端连接到服务器时,您都必须在每个客户端上设置数据库副本并与服务器同步,但我想您已经做到了。
我会在客户端的每个表上都有一个位列和一个日期戳,这样我就可以检查哪些记录已离线更改。在服务器端,记录对对象的最后更新的日期戳列将起到作用。
至于具有自动增量的主键,我会松开它们,因为您需要自己设置它们以防止创建具有相同键的两条记录(您可能需要在同步时更改它们)。
这是简单的部分...现在事情会变得一团糟...您需要考虑到这会给您带来很多麻烦...会发生各种或不希望发生的事件,例如:-两个用户离线更改同一记录。- 一位用户在线更改记录,另一位离线更改 - 一位用户在线删除记录,而另一位用户离线处理记录
潜在问题的清单一直在继续,在您开始解决它们之前,您必须列举每一个问题并与您的客户一起记录他们希望系统如何处理每个案例,否则当他们丢失数据时(无论您如何处理,都会发生这种情况)做)这将是你的错,而不是他们的错。
我建议您为数据库中可以离线更改的每个表构建一个版本控制系统。用户会弄乱他们的数据,执行回滚对他们来说会很好。
我现在已经在不同的地方做过几次了(参见下面史蒂夫·兰德斯的回答),我强烈建议你不要使用正常的复制——尤其是在涉及多个数据库的情况下。
我这么说的原因是,根据我的经验,复制不够聪明,无法处理当您使远程站点重新联机时(或当您决定将新站点添加到整个网络时)可能出现的问题。
如果您只有 2 或 3 个不同的数据库,但如果您谈论的是可以随时在线/离线的许多不同位置,并且可以随时添加(或删除或修改)信息,则复制对于这种事情来说很好在这些位置中,您很快就会使某些东西陷入混乱状态。从技术上讲,这不是一件很令人满意的事情,但是您总是能够想到特殊情况,您不希望复制按照设计去做它想做的事情。
如果您只处理 2 个数据库,那么显然复制问题会变得更加简单,您可能会发现可以使用合并复制来完成这项工作(尽管您必须注意数据库设计)。
我刚买了一本 Apress SQL Server 2005 复制圣经的二手副本(不在办公室,所以没有作者在手,但这是一本值得推荐的怪物大部头)——在前几章中,我开始意识到,如果您真的要在两个(或更多)端更改数据,复制并不是一个灵丹妙药的解决方案。:-)
这通常称为公文包模型,您可以使用 Microsoft Synchronization Services for ADO.NET