事务复制的可更新订阅

适用于: SQL Server 2008 (及更高版本)

注释

此功能将在Microsoft SQL Server 的未来版本中删除。 避免在新开发工作中使用此功能,并计划修改当前使用此功能的应用程序。

在 SQL Server 2014 中,事务复制通过可更新的订阅和对等复制支持订阅服务器上的更新。 以下是两种类型的可更新订阅:

  • 立即更新。 发布者和订阅者必须连接以在订阅者处更新数据。

  • 排队更新发布服务器和订阅服务器不必连接到订阅服务器上的更新数据。 可以在订阅服务器或发布服务器脱机时进行更新。

在订阅服务器上更新数据时,数据首先传播到发布服务器,然后传播到其他订阅服务器。 如果使用即时更新,则更改会立即使用两阶段提交协议进行传播。 如果使用队列更新,则更改存储在队列中;然后,每当网络连接可用时,队列中的事务在发布服务器上异步应用。 由于更新以异步方式传播到发布服务器,因此发布服务器或其他订阅服务器可能更新了相同的数据,应用更新时可能会发生冲突。 根据创建发布时设置的冲突解决策略来检测和解决冲突。

在“新建发布向导”中创建可更新订阅的事务性发布时,将同时启用即时更新和排队更新。 如果使用存储过程创建发布,则可以启用一个或多个选项。 创建发布订阅时,可以指定要使用的更新模式。 然后,可以根据需要在更新模式之间进行切换。 有关详细信息,请参阅以下部分“在更新模式之间切换”。

若要为事务发布启用可更新订阅, 请为事务发布启用更新订阅

若要为事务发布创建可更新订阅,请参阅 创建事务发布的可更新订阅

在更新模式之间切换

使用可更新订阅时,可以指定订阅应使用一种更新模式,然后切换到另一种(如果应用程序需要)。 例如,可以指定订阅应使用即时更新,但如果系统故障导致网络连接丢失,请切换到排队更新。

注释

复制不会在更新模式之间自动切换。 必须通过 SQL Server Management Studio 设置更新模式,否则应用程序必须调用 sp_setreplfailovermode(Transact-SQL) 在模式之间切换。

如果从立即更新切换到排队更新,则无法切换回立即更新,直到订阅者和发布者已连接并且队列读取器代理已将队列中的所有挂起消息应用到发布者为止。

在更新模式之间切换

若要在更新模式之间切换,必须为这两种更新模式启用发布和订阅,然后在必要时在它们之间切换。 有关详细信息,请参阅
在可更新事务订阅的更新模式之间切换

使用可更新订阅时须考虑的事项

  • 为更新订阅或排队更新订阅启用发布后,不能对发布禁用该选项(尽管订阅不需要使用它)。 若要禁用该选项,必须删除发布并创建一个新发布。

  • 不支持重新发布数据。

  • 复制将 msrepl_tran_version 列添加到已发布的表,以便进行跟踪。 由于此附加列,所有 INSERT 语句都应包括列列表。

  • 若要对支持更新订阅的发布的表格进行架构更改,必须在发布服务器和订阅服务器上停止表上的所有活动,并且必须在进行任何架构更改之前将未完成的数据更改传播到所有节点。 这可确保挂账事务不会与待处理的架构更改冲突。 架构更改传播到所有节点后,活动可以在已发布的表上恢复。 有关详细信息,请参阅停止复制拓扑(复制 Transact-SQL 编程)

  • 如果打算在更新模式之间切换,队列读取器代理必须在初始化订阅后至少运行一次(默认情况下,队列读取器代理会持续运行)。

  • 如果订阅服务器数据库是水平分区的,并且该分区中有一些行存在于订阅服务器上,但不在发布服务器上,则订阅服务器无法更新预先存在的行。 尝试更新这些行将返回错误。 应从表中删除行,然后在发布服务器上添加行。

订阅服务器上的更新

  • 即使订阅已过期或处于非活动状态,订阅服务器上的更新也会传播到发布服务器。 确保删除或重新初始化任何此类订阅。

  • 如果使用 TIMESTAMPIDENTITY 列,并且它们作为基本数据类型进行复制,则不应该在订阅者处更新这些列中的值。

  • 订阅者无法更新或插入textntextimage值,因为无法在复制更改跟踪触发器中从插入或删除的表中进行读取。 同样,订阅者不能使用 WRITETEXTUPDATETEXT 来更新或插入 textimage 值,因为数据会被发布服务器覆盖。 相反,可以将 textimage 列分到单独的表中,并在一个事务中修改这两个表。

    若要在订阅服务器上更新大型对象,请使用数据类型varchar(max), nvarchar(max), varbinary(max),分别替代数据类型text, ntext, 和image

  • 对生成重复项的唯一键(包括主键)的更新(例如,形式为 UPDATE <column> SET <column> =<column>+1 的更新)是不被允许的,并将因唯一性冲突而被拒绝。 这是因为在订阅服务器上进行的集合更新通过复制传播为受影响的每一行的单个 UPDATE 语句。

  • 如果订阅服务器数据库是水平分区的,并且分区中有一些行存在于订阅服务器上,但不存在于发布服务器上,则订阅服务器无法更新预先存在的行。 尝试更新这些行将返回错误。 应从表中删除行,然后再次插入。

用户定义的触发器

  • 如果应用程序需要订阅服务器上的触发器,则应使用 NOT FOR REPLICATION 发布服务器和订阅服务器上的选项定义触发器。 这可确保触发器仅在原始数据发生更改时被触发,而不是在该更改被复制时。

    确保在复制触发器更新表时,用户定义的触发器不会被触发。 这是通过调用用户定义的触发器正文中的过程 sp_check_for_sync_trigger 来实现的。 有关详细信息,请参阅sp_check_for_sync_trigger(Transact-SQL)。

立即更新

  • 对于即时更新的订阅,在订阅端的更改会传播到发布端,并通过Microsoft分布式事务处理协调器(MS DTC)加以应用。 确保在发布服务器和订阅服务器上安装和配置 MS DTC。 有关详细信息,请参阅 Windows 文档。

  • 立即更新订阅使用的触发器需要与发布服务器建立连接才能复制更改。

  • 如果发布允许立即更新订阅,并且发布中的项目具有列筛选器,则不能在没有默认值的情况下筛选出不可为 null 的列。

排队更新

  • 合并发布中包含的表不能作为允许排队更新订阅的事务性发布的一部分发布。

  • 在使用排队更新时,不建议对主键列进行更新,因为主键用作所有查询的记录定位符。 当冲突解决策略设置为“订阅者获胜”时,应谨慎更新主键。 如果对主键的更新同时在发布服务器和订阅服务器上进行,则结果将是两行,其中包含不同的主键。

  • 对于数据类型 SQL_VARIANT 的列:当在订阅服务器上插入或更新数据时,队列读取器代理在从订阅服务器复制数据到队列时,会按如下方式进行映射:

    • BIGINT、、DECIMALNUMERICMONEYSMALLMONEY映射到 NUMERIC

    • BINARYVARBINARY 被映射到 VARBINARY 数据。

冲突检测和解决

  • 对于订阅方优胜冲突策略:不支持对主键列更新的冲突解决。

  • 由于外键约束失败而导致的冲突无法通过复制解决:

    • 如果冲突不预期且数据分区良好(订阅服务器不更新相同行),则可以对发布服务器和订阅服务器使用外键约束。

    • 如果预期会发生冲突:采用“订阅服务器优先”的冲突解决方案时,不应在发布服务器或订阅服务器上使用外键约束;采用“发布服务器优先”的冲突解决方案时,不应在订阅服务器上使用外键约束。

另请参阅

对等事务复制
事务复制
发布数据和数据库对象
订阅刊物