对等复制中的冲突检测

对等事务复制允许在拓扑中的任何节点上插入、更新或删除数据,并将数据更改传播到其他节点。 由于可以在任意节点上更改数据,因此不同节点上的数据更改可能会相互冲突。 如果一行在多个节点上被修改,当该行被传播到其他节点时,可能会导致冲突,甚至导致更新被覆盖或丢失。

在 SQL Server 2008 及更高版本中,对等复制提供了一种选项,以启用跨对等拓扑的冲突检测。 此选项有助于防止因未检测到的冲突而导致的问题,包括不一致的应用程序行为和丢失的更新。 启用此选项后,默认情况下,冲突更改被视为导致分发代理失败的关键错误。 发生冲突时,拓扑保持不一致状态,直到冲突得到解决,并且数据在整个拓扑中保持一致。

注释

若要避免潜在的数据不一致,请确保避免对等拓扑中的冲突,即使启用了冲突检测。 为了确保对特定行的写入操作仅在一个节点上执行,访问和更改数据的应用程序必须对插入、更新和删除操作进行分区。 此分区可确保对源自一个节点的给定行的修改与拓扑中的所有其他节点同步,然后再由其他节点修改该行。 如果应用程序需要复杂的冲突检测和解决功能,请使用合并复制。 有关详细信息,请参阅合并复制并检测和解决合并复制冲突

了解冲突和冲突检测

在单个数据库中,由不同应用程序对同一行所做的更改不会导致冲突。 这是因为事务已序列化,并且锁用于处理并发更改。 在异步分布式系统(如对等复制)中,事务在每个节点上独立运行;并且没有跨多个节点序列化事务的机制。 可以使用两阶段提交等协议,但这会显著影响性能。

在对等复制等系统中,在单个对等方提交更改时,不会检测到冲突。 当这些更改被复制并应用到其他对等方时,才会检测出这些更改。 在对等复制中,存储过程根据每个已发布表中的隐藏列对每个节点应用更改,从而检测到冲突。 此隐藏列存储一个 ID,该 ID 结合了你为每个节点指定的 发起方 ID 和行的版本。 在同步期间,分发代理会为每个表执行过程。 这些程序应用来自其他对等方的插入、更新和删除操作。 如果其中一个过程在读取隐藏列值时检测到冲突,则会引发错误 22815,其严重级别为 16:

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_addpublicationsp_configure_peerconflictdetection

    如果使用存储过程配置冲突检测,则可以指定检测到冲突时分发代理是否应停止应用更改。 默认值为代理停止。 建议使用默认设置。

处理冲突

在对等复制中发生冲突时,将引发对等冲突检测警报。 建议配置此警报,以便在发生冲突时收到通知。 有关警报的详细信息,请参阅 “对复制代理事件使用警报”。

分发代理停止并引发警报后,使用以下方法之一来处理发生的冲突:

  • 从包含所需数据的节点(建议的方法)的备份中重新初始化检测到冲突的节点。 此方法可确保数据处于一致状态。

  • 尝试通过启用分发代理来继续应用更改,以重新同步节点。

    1. 执行sp_changepublication:为@property参数和true@value参数指定“p2p_continue_onconflict”。

    2. 重启分发代理。

    3. 使用冲突查看器验证检测到的冲突,并确定所涉及的行、冲突类型和获胜者。 冲突是根据在配置期间指定的发起方 ID 值解决的:源自具有最高 ID 的节点的行将赢得冲突。 有关详细信息,请参阅查看数据冲突与事务性出版物(SQL Server Management Studio)。

    4. 运行验证以确保有冲突的行正确合并。 有关详细信息,请参阅 “验证复制的数据”。

      注释

      如果此步骤后数据不一致,则必须手动更新具有最高优先级的节点上的行,然后让更改从此节点传播。 如果拓扑中没有进一步的冲突更改,所有节点都将处于一致状态。

    5. 执行sp_changepublication:为@property参数指定“p2p_continue_onconflict”,为false和@value参数指定相应的值。

另请参阅

对等事务复制