Skip to content

SQLServer 合并复制配置

合并复制概述

合并复制是 SQL Server 提供的一种双向数据同步技术,允许在发布服务器和订阅服务器之间双向复制数据。合并复制适用于分布式环境,如移动应用、分支办公室和离线操作场景,支持订阅服务器在离线状态下进行数据修改,在线后自动同步。

合并复制的核心特性

  • 双向数据同步:允许在发布服务器和订阅服务器上都进行数据修改
  • 自动冲突检测与解决:内置冲突检测机制,支持多种冲突解决策略
  • 离线操作支持:订阅服务器可离线修改数据,在线后自动同步
  • 灵活的拓扑结构:支持星型、环型和网状拓扑
  • 基于行的增量复制:只复制修改的行,减少网络流量
  • 身份范围管理:自动管理身份列,避免身份冲突

合并复制的组成架构

组件核心功能生产角色
发布服务器 (Publisher)源数据库管理、发布配置、冲突解决中心数据节点
分发服务器 (Distributor)存储复制元数据和快照、管理复制代理复制协调中心
订阅服务器 (Subscriber)接收复制数据、允许本地修改分布式数据节点
快照代理生成初始快照初始化数据同步
合并代理处理数据合并和冲突解决实时数据同步

版本差异支持

SQL Server 版本合并复制关键特性变化生产适用场景
2012增强的合并复制监控、Always On 可用性组集成企业级分布式应用
2014内存中 OLTP 支持、增强的性能高并发分布式系统
2016JSON 数据类型支持、增强的安全性现代 Web 应用数据同步
2017Linux 支持、增强的代理管理混合云环境
2019大数据群集支持、增强的可用性大规模分布式数据处理
2022智能查询处理支持、增强的性能监控云原生应用数据同步

合并复制工作原理

数据同步流程

  1. 初始快照生成:快照代理生成发布数据库的初始快照
  2. 订阅初始化:订阅服务器应用初始快照,建立初始数据一致性
  3. 数据修改:允许在发布服务器和订阅服务器上独立修改数据
  4. 变更跟踪:通过元数据表跟踪所有数据变更
  5. 数据合并:合并代理定期或按需合并数据更改
  6. 冲突检测:检测并记录数据冲突
  7. 冲突解决:根据预设规则自动解决冲突
  8. 数据同步:将解决冲突后的数据同步到所有节点

冲突类型与解决机制

冲突类型描述默认解决策略生产建议
更新-更新冲突同一行在不同节点被更新发布服务器优先根据业务需求选择,如时间戳优先
插入-插入冲突同一主键在不同节点被插入发布服务器优先使用身份范围管理避免
删除-更新冲突一行在一个节点被删除,在另一个节点被更新删除操作优先谨慎处理,建议保留数据
删除-删除冲突同一行在不同节点被删除无冲突无需特殊处理

生产场景配置步骤

前提条件

  • 确保 SQL Server 已安装复制组件
  • 确保所有服务器之间网络连通
  • 确保有足够的磁盘空间存储快照
  • 配置适当的防火墙规则,允许复制流量

步骤1:配置分发服务器

GUI 配置

  1. 打开 SSMS,连接到要配置为分发服务器的实例
  2. 右键点击 "复制" 节点,选择 "配置分发"
  3. 选择本地分发服务器
  4. 配置快照文件夹(建议使用专用共享文件夹)
  5. 配置分发数据库(默认使用 distribution 数据库)
  6. 完成配置

T-SQL 配置

sql
-- 启用分发服务器
USE master;
EXEC sp_adddistributor @distributor = @@SERVERNAME, @password = 'StrongDistributorPass123!';

-- 创建分发数据库
EXEC sp_adddistributiondb @database = N'distribution', 
    @data_folder = N'C:\Program Files\Microsoft SQL Server\MSSQL16.MSSQLSERVER\MSSQL\Data', 
    @log_folder = N'C:\Program Files\Microsoft SQL Server\MSSQL16.MSSQLSERVER\MSSQL\Data', 
    @log_file_size = 2, 
    @min_distretention = 0, 
    @max_distretention = 72, 
    @history_retention = 48, 
    @deletebatchsize_xact = 5000, 
    @deletebatchsize_cmd = 2000, 
    @security_mode = 1;

-- 配置发布服务器
EXEC sp_adddistpublisher @publisher = @@SERVERNAME, 
    @distribution_db = N'distribution', 
    @security_mode = 1, 
    @working_directory = N'\\SERVER\Snapshot', 
    @trusted = N'false', 
    @thirdparty_flag = 0, 
    @publisher_type = N'MSSQLSERVER';

步骤2:创建合并发布

GUI 配置

  1. 打开 SSMS,连接到发布服务器
  2. 右键点击 "复制" → "本地发布",选择 "新建发布"
  3. 选择要发布的数据库
  4. 选择发布类型为 "合并发布"
  5. 选择要发布的表,配置以下关键选项:
    • 启用身份范围管理
    • 配置冲突解决策略
    • 设置跟踪级别为 "行级别"
  6. 配置快照代理,设置快照生成计划
  7. 配置合并代理安全设置
  8. 完成发布创建

T-SQL 配置

sql
-- 启用数据库的合并发布
USE master;
EXEC sp_replicationdboption @dbname = N'AdventureWorks2019', 
    @optname = N'merge publish', 
    @value = N'true';

-- 创建合并发布
EXEC sp_addmergepublication @publication = N'AdventureWorksMergePub', 
    @description = N'AdventureWorks 合并发布', 
    @sync_mode = N'native', 
    @retention = 14, 
    @allow_push = N'true', 
    @allow_pull = N'true', 
    @allow_anonymous = N'false', 
    @enabled_for_internet = N'false', 
    @snapshot_in_defaultfolder = N'true', 
    @compress_snapshot = N'true', 
    @ftp_port = 21, 
    @ftp_subdirectory = N'ftp', 
    @ftp_login = N'anonymous', 
    @allow_subscription_copy = N'false', 
    @add_to_active_directory = N'false', 
    @dynamic_filters = N'false', 
    @conflict_retention = 14, 
    @keep_partition_changes = N'false', 
    @allow_synctoalternate = N'false', 
    @max_concurrent_merge = 5, 
    @replicate_ddl = 1, 
    @conflict_logging = N'publisher';

-- 添加发布文章(Product表)
EXEC sp_addmergearticle @publication = N'AdventureWorksMergePub', 
    @article = N'Product', 
    @source_owner = N'Production', 
    @source_object = N'Product', 
    @type = N'table', 
    @identityrangemanagementoption = N'auto', 
    @pub_identity_range = 10000, 
    @identity_range = 1000, 
    @threshold = 80, 
    @column_tracking = N'true';

-- 配置快照代理
EXEC sp_addmergepublication_snapshot @publication = N'AdventureWorksMergePub', 
    @frequency_type = 1, 
    @frequency_interval = 1, 
    @frequency_subday = 4, 
    @frequency_subday_interval = 15, 
    @active_start_time_of_day = 0, 
    @active_end_time_of_day = 235959, 
    @active_start_date = 0, 
    @active_end_date = 0, 
    @publisher_security_mode = 1;

步骤3:创建合并订阅

推送订阅配置

sql
-- 创建推送订阅
EXEC sp_addmergesubscription @publication = N'AdventureWorksMergePub', 
    @subscriber = N'SUBSCRIBER_SERVER', 
    @subscriber_db = N'AdventureWorks2019_MergeSub', 
    @subscription_type = N'Push', 
    @sync_type = N'automatic', 
    @priority = 0, 
    @subscriber_type = N'local';

-- 配置推送订阅代理
EXEC sp_addmergepushsubscription_agent @publication = N'AdventureWorksMergePub', 
    @subscriber = N'SUBSCRIBER_SERVER', 
    @subscriber_db = N'AdventureWorks2019_MergeSub', 
    @job_login = null, 
    @job_password = null, 
    @subscriber_security_mode = 1, 
    @frequency_type = 64, 
    @frequency_interval = 1, 
    @frequency_subday = 4, 
    @frequency_subday_interval = 30, 
    @active_start_time_of_day = 0, 
    @active_end_time_of_day = 235959, 
    @active_start_date = 0, 
    @active_end_date = 0;

请求订阅配置

  1. 在订阅服务器上打开 SSMS
  2. 右键点击 "复制" → "本地订阅",选择 "新建订阅"
  3. 选择 "查找发布"
  4. 连接到发布服务器,选择要订阅的发布
  5. 选择订阅数据库
  6. 配置合并代理安全设置
  7. 配置同步计划
  8. 完成订阅创建

生产场景最佳实践

分支办公室数据同步场景

业务需求

  • 总部和多个分支办公室之间需要双向数据同步
  • 分支办公室可能离线工作
  • 每天需要生成销售报告

架构设计

  • 总部服务器作为发布服务器
  • 每个分支办公室作为订阅服务器
  • 使用中心辐射型拓扑
  • 配置每日增量合并,每周完整同步

关键配置

  • 启用身份范围管理,避免身份冲突
  • 配置冲突解决策略为 "时间戳优先"
  • 启用快照压缩,减少网络流量
  • 配置冲突日志记录,定期分析冲突

移动应用数据同步场景

业务需求

  • 移动应用需要离线工作
  • 数据需要在移动设备和服务器之间同步
  • 数据量较小,但并发较高

架构设计

  • 云服务器作为发布服务器
  • 移动应用通过中间层连接订阅服务器
  • 使用 Web 同步,支持 HTTPS
  • 配置按需合并,用户触发同步

关键配置

  • 启用 Web 同步,配置 SSL 加密
  • 配置短保留期,减少元数据量
  • 使用行筛选,只复制用户相关数据
  • 配置冲突解决策略为 "订阅服务器优先"

冲突管理与监控

冲突检测与解决

查看冲突

sql
-- 查看所有合并冲突
EXEC sp_showmergeconflicts @publication = N'AdventureWorksMergePub';

-- 查询特定表的冲突
SELECT * FROM MSmerge_conflict_ProductionProduct;

自定义冲突解决器

使用存储过程解决器

  1. 创建冲突解决存储过程
  2. 注册冲突解决器
  3. 为发布文章配置自定义解决器
sql
-- 创建冲突解决存储过程
CREATE PROCEDURE dbo.ResolveProductConflict
    @table_name sysname,
    @rowguid uniqueidentifier,
    @subscriber_name sysname,
    @subscriber_db sysname,
    @log_conflict INT OUTPUT
AS
BEGIN
    -- 自定义冲突解决逻辑
    -- 示例:保留价格较高的产品记录
    UPDATE MSmerge_tombstone
    SET version = version + 1
    WHERE rowguid = @rowguid;
    
    SET @log_conflict = 0;
END;
GO

合并复制监控

使用动态管理视图

sql
-- 查看合并代理状态
SELECT 
    name AS agent_name,
    status,
    status_desc,
    last_sync_time,
    next_sync_time,
    current_task
FROM sys.dm_repl_agents
WHERE type = 3; -- 3: 合并代理

-- 查看合并复制统计信息
SELECT 
    publication,
    subscriber,
    subscriber_db,
    upload_rows_total,
    download_rows_total,
    conflicts_total,
    start_time,
    end_time,
    duration = DATEDIFF(minute, start_time, end_time)
FROM MSmerge_sessions
ORDER BY end_time DESC;

-- 查看身份范围使用情况
SELECT 
    publication,
    article,
    subscriber,
    current_identity_value,
    last_identity_range_used,
    identity_range_size
FROM sysmerge_identity_range_allocations;

使用复制监视器

  1. 打开 SSMS,连接到发布服务器
  2. 右键点击 "复制" 节点,选择 "启动复制监视器"
  3. 查看合并代理状态和性能指标
  4. 查看冲突信息和解决结果

性能优化与故障排除

性能优化

  1. 网络优化

    • 使用压缩快照减少网络流量
    • 优化网络带宽,考虑使用 CDN 或专用网络
    • 配置合适的同步频率,避免频繁合并
  2. 数据优化

    • 使用行筛选和列筛选减少复制数据量
    • 避免复制大对象(LOB),如 TEXT、IMAGE 等
    • 优化表结构,避免频繁修改的列
  3. 冲突优化

    • 设计业务逻辑避免冲突
    • 使用合适的冲突解决策略
    • 定期分析冲突模式,优化数据模型
  4. 代理优化

    • 调整合并代理的并行线程数
    • 优化合并代理的内存使用
    • 配置合适的代理账户权限

常见故障排除

故障现象可能原因解决方案
合并代理失败网络连接问题检查网络连接,测试端口连通性
权限问题检查代理账户权限,确保有足够权限
冲突未解决手动解决冲突,调整冲突解决策略
元数据损坏重新初始化订阅,清理合并元数据
身份冲突身份范围配置不当调整身份范围大小和阈值
手动插入身份值避免手动插入身份值,使用自动身份范围
快照生成失败磁盘空间不足清理快照文件夹,增加磁盘空间
权限问题检查快照代理账户权限
数据库锁定确保数据库没有长时间锁定

合并复制维护

定期维护任务

  1. 清理元数据

    • 定期清理合并元数据,减少系统表大小
    • 使用 sp_mergesubscription_cleanup 存储过程
  2. 重新生成快照

    • 定期重新生成快照,确保数据一致性
    • 建议每周或每月重新生成一次
  3. 更新统计信息

    • 更新发布和订阅数据库的统计信息
    • 优化查询性能,提高合并效率
  4. 检查复制健康状态

    • 定期检查合并代理状态
    • 查看冲突报告,分析冲突趋势
    • 监控复制性能指标

备份与恢复

发布服务器备份

  • 备份发布数据库和分发数据库
  • 备份复制元数据
  • 记录复制配置,便于恢复

订阅服务器恢复

  • 对于订阅服务器故障,可重新初始化订阅
  • 对于发布服务器故障,需要重新配置复制

常见问题 (FAQ)

合并复制和事务复制有什么区别?

合并复制支持双向数据同步,允许在发布服务器和订阅服务器上都进行数据修改,适用于分布式环境和离线操作。事务复制主要是单向数据同步,订阅服务器通常是只读的,适用于读写分离和数据分发场景。

如何避免合并复制中的身份冲突?

使用自动身份范围管理是避免身份冲突的最佳方法。配置合适的身份范围大小和阈值,确保每个节点有足够的身份值。避免手动插入身份值,使用自动增长的身份列。

合并复制支持多少个订阅服务器?

SQL Server 合并复制理论上支持大量订阅服务器,但实际数量取决于网络带宽、数据量和合并频率。建议根据实际测试结果确定合适的订阅服务器数量,一般不超过 100 个。

如何提高合并复制的性能?

提高合并复制性能的方法包括:

  • 优化网络连接,使用压缩
  • 减少复制数据量,使用行筛选和列筛选
  • 调整合并代理的同步频率和并行线程数
  • 优化冲突解决策略,减少冲突
  • 定期清理元数据,维护复制健康状态

如何迁移合并复制到新服务器?

迁移合并复制的步骤:

  1. 在新服务器上配置分发
  2. 重新创建合并发布,保持相同的配置
  3. 重新创建订阅,重新初始化
  4. 验证复制状态,确保数据一致
  5. 切换应用程序连接到新服务器

合并复制支持跨版本复制吗?

是的,合并复制支持跨版本复制,但需要注意版本兼容性。一般来说,订阅服务器的版本可以高于或等于发布服务器的版本,但不建议订阅服务器版本低于发布服务器版本。跨版本复制可能会有一些功能限制,建议查阅官方文档了解具体限制。

总结

合并复制是 SQL Server 中强大的双向数据同步技术,适用于分布式环境、移动应用和离线操作场景。通过合理的配置、监控和维护,可以实现高效、可靠的数据同步。

在实施合并复制时,建议:

  1. 合理设计拓扑结构:根据业务需求选择合适的拓扑,如中心辐射型或网状拓扑
  2. 优化身份范围管理:配置合适的身份范围大小和阈值,避免身份冲突
  3. 选择合适的冲突解决策略:根据业务需求选择冲突解决策略,如发布服务器优先、时间戳优先等
  4. 建立完善的监控体系:定期监控合并代理状态、冲突情况和性能指标
  5. 定期维护复制:清理元数据、重新生成快照、更新统计信息
  6. 准备故障恢复计划:制定详细的备份和恢复策略,确保数据安全

通过遵循这些最佳实践,可以确保合并复制的稳定运行,满足业务的数据同步需求,提高系统的可用性和可靠性。