对等复制中的冲突检测
通过对等事务复制,可以在拓扑中的任何节点插入、更新或删除数据并将数据更改传播到其他节点。 由于可在任何节点上更改数据,因此在不同节点上进行的数据更改可能会相互冲突。 如果在多个节点上修改了某一行,则将该行传播给其他节点时会导致冲突甚至丢失更新。
SQL Server 2008 和更高版本中的对等复制提供了在对等拓扑中启用冲突检测的选项。 此选项将有助于防止出现因未检测到的冲突而引发的各种问题,包括不一致的应用程序行为和丢失的更新。 启用该选项后,默认情况下,发生冲突的更改将被视为导致分发代理失败的关键错误。 发生冲突时,拓扑将始终处于不一致的状态,直至冲突得以解决而且拓扑中的数据保持一致。
注意 |
---|
为了避免潜在的数据不一致性,即便已经启用了冲突检测功能,也应尽力避免对等拓扑中发生冲突。 为了确保仅在某一个节点上执行特定行的写入操作,访问并更改数据的应用程序必须对其插入、更新和删除操作进行分区。 分区可确保在一个节点上对给定行进行的修改可以在其他节点修改该行之前,与拓扑中的所有其他节点同步。 如果应用程序需要完善的冲突检测与解决功能,请使用合并复制。 有关详细信息,请参阅合并复制和检测并解决合并复制冲突。 |
了解冲突和冲突检测
在单个数据库中,不同应用程序对同一行进行的更改不会导致冲突。 原因在于,事务已经过序列化,并使用锁定来处理并发更改。 在异步分布式系统(如对等复制)中,事务独立作用于每个节点,而且没有用来跨多个节点对事务进行序列化的机制。 可以使用两阶段提交之类的协议,但是这会显著影响性能。
在对等复制之类的系统中,在单个对等节点上提交更改之后将检测不到冲突。 相反,在复制这些更改并将其应用于其他对等节点之后,才能够检测到这些更改。 在对等复制中,用来将更改应用于每个节点的存储过程会基于每个已发布表中的某个隐藏列来检测冲突。 该隐藏列所存储的 ID 将您为每个节点指定的“发起方 ID”与行版本结合起来。 在同步期间,分发代理会针对每个表执行同步过程。 这些过程会应用来自其他对等节点的插入、更新和删除操作。 如果某个过程在读取该隐藏列的值时检测到冲突,将会引发严重级别为 16 的错误 22815:
A conflict of type '%s' was detected at peer %d between peer %d (incoming), transaction id %s and peer %d (on disk), transaction id %s
默认情况下,此错误会导致分发代理停止向该节点应用所做的更改。 有关如何处理所检测到冲突的信息,请参阅本主题稍后部分中的“处理冲突”。
注意 |
---|
隐藏列只能由通过专用管理员连接 (DAC) 登录的用户来访问。 有关 DAC 的信息,请参阅用于数据库管理员的诊断连接。 |
对等复制检测到下列类型的冲突:
插入-插入
每个表中所有参与对等复制的行都使用主键值进行唯一标识。 在将具有相同键值的行插入到多个节点时,会发生插入-插入冲突。
更新-更新
在多个节点上更新了同一行时发生。
插入-更新
在以下情况下发生:在一个节点上更新了某行,但是在另一个节点上删除了该行,然后又重新插入该行。
插入-删除
在以下情况下发生:在一个节点上删除了某行,但是在另一个节点上删除了该行,然后又重新插入该行。
更新-删除
在以下情况下发生:在一个节点上更新了某行,但是在另一个节点上删除了该行。
删除-删除
在多个节点上删除了同一行时发生。
启用冲突检测
若要使用冲突检测,所有节点都必须运行 SQL Server 2008 或更高版本;并且必须为所有节点启用检测。在 SQL Server 2008 和更高版本中,默认情况下,在 SQL Server Management Studio 中启用冲突检测。 我们建议您启用冲突检测,即使在应当不会有任何冲突时也是如此。 可以使用 Management Studio 或 Transact-SQL 存储过程来启用和禁用冲突检测:
在 Management Studio 中,可以使用**“发布属性”对话框的“订阅选项”页或配置对等拓扑向导的“配置拓扑”**页来启用和禁用冲突检测。 有关详细信息,请参阅对等复制中的冲突检测。
如果您使用 Management Studio 来配置冲突检测,则分发代理将配置为在检测到冲突时停止应用所做的更改。
还可以使用 sp_addpublication 或 sp_configure_peerconflictdetection 存储过程来启用和禁用冲突检测。 有关详细信息,请参阅对等复制中的冲突检测。
如果您使用存储过程来配置冲突检测,则可以指定在检测到冲突时分发代理是否应当停止应用所做的更改。 默认值是让分发代理停止。 我们建议您使用默认设置。
处理冲突
在对等复制中发生冲突时,将会引发Peer-to-peer conflict detection alert。 我们建议您配置该警报,以便在发生冲突时获得通知。 有关警报的更多信息,请参阅对复制代理事件使用警报。
在分发代理停止并且引发警报之后,请使用下列方法之一来处理所发生的冲突:
从包含必需数据的节点的备份中重新初始化检测到冲突的节点(建议的方法)。 此方法可确保数据保持一致状态。
尝试通过允许分发代理继续应用所做的更改,再次同步节点:
执行 sp_changepublication:将 @property 参数的值指定为 'p2p_continue_onconflict',并将 @value 参数的值指定为 true。
重新启动分发代理。
使用冲突查看器验证检测到的冲突,并确定所涉及的行、冲突类型以及入选方。 冲突可基于您在配置过程中指定的发起方 ID 值来解决:源自具有最高 ID 的节点的行将在冲突中入选。 有关详细信息,请参阅查看事务性发布的数据冲突 (SQL Server Management Studio)。
运行验证步骤以确保发生冲突的行能够正确收敛。 有关详细信息,请参阅验证已复制的数据。
注意 如果在执行该步骤之后数据不一致,则必须在具有最高优先级的节点上手动更新行,然后允许从该节点传播所做的更改。 如果拓扑中不再有发生冲突的更改,则所有节点将保持一致状态。
执行 sp_changepublication:将 @property 参数的值指定为 'p2p_continue_onconflict',并将 @value 参数的值指定为 false。