3. 复制代理体系与作业调度

SQL Server 复制的“自动化”并不是一个进程包办所有事情,而是由一组职责单一的代理(Agent)分工协作完成。理解每个代理“读什么、写什么、什么时候被唤醒”,是排查复制延迟、数据不一致和作业失败的基础。本节先建立代理协作的整体视图,再逐一说明各代理的职责边界、关键参数与作业调度管理方式。

一、代理协作的整体视图

复制拓扑中,发布服务器、分发服务器和订阅服务器之间通过分发数据库(distribution)解耦。发布服务器上的变更先被捕获并写入分发数据库,再由分发代理推送到订阅服务器。不同复制类型使用的代理组合不同:

  • 快照复制:快照代理 + 分发代理。
  • 事务复制:快照代理(初始化)+ 日志读取代理 + 分发代理;若使用排队更新订阅,还会涉及队列读取代理。
  • 合并复制:快照代理 + 合并代理;合并代理同时承担变更上传与下载。

下图给出事务复制(含排队更新)场景下各代理与数据库对象之间的数据流关系,可作为后续排查的定位地图。

发布服务器 发布数据库 事务日志 (ldf) 分发服务器 分发数据库 MSrepl_commands MSrepl_transactions 订阅服务器 订阅数据库 队列表 (queues) 快照代理 Snapshot Agent 日志读取代理 Log Reader Agent 分发代理 Distribution Agent 队列读取代理 Queue Reader Agent 合并代理 Merge Agent 数据流说明: 事务/命令流(日志读取→分发→订阅) 排队更新回传(队列读取代理) 合并代理双向同步

二、各代理的职责与关键行为

快照代理负责生成初始数据集。它连接发布数据库,对已发布表加锁(默认使用并发快照,减少阻塞),将数据以 bcp 文件形式写入快照文件夹,同时把架构脚本、约束、索引等写入同一目录。快照代理还会在分发数据库中登记同步集(sync set)信息。它的典型作业名形如 REPL-Snapshot-<发布名>-<发布数据库名>。快照代理不是一次性任务:当发布属性变更、需要重新初始化订阅时,会再次运行。

日志读取代理只存在于事务复制中。它扫描发布数据库的事务日志,把标记为复制的事务转换为命令,写入分发数据库的 MSrepl_transactions 和 MSrepl_commands 表。它不直接接触订阅服务器,因此日志读取代理正常并不代表订阅端已收到数据。关键参数包括 -PollingInterval(扫描日志的间隔秒数,默认 5 秒)和 -ReadBatchSize(每批读取的事务数)。当日志读取代理停止时,发布数据库日志可能因“复制未读取”而无法截断,这是常见的日志膨胀原因。

分发代理负责把分发数据库中的命令应用到订阅服务器。对事务复制,它按事务顺序将命令投递到订阅数据库;对快照复制,它负责把快照文件复制到订阅端并应用。分发代理分为推送订阅(在分发服务器运行)和拉取订阅(在订阅服务器运行)两种部署位置,这直接影响网络带宽占用和故障排查入口。关键参数有 -CommitBatchSize(每批提交的事务数)、-CommitBatchThreshold(每批提交的命令数)和 -MaxDeliveredTransactions。

合并代理用于合并复制,承担双向同步:先从订阅端上传变更到发布端,再从发布端下载变更到订阅端。它依赖生成器(generation)和行版本(lineage)来判定冲突,并按冲突解决程序(如优先级、自定义 COM)决定保留哪一行。合并代理的调度通常比事务复制更“粗粒度”,因为每次运行都要做元数据比较和冲突检测。

队列读取代理用于排队更新订阅。当订阅端在排队更新模式下修改数据时,变更先进入订阅数据库的队列表,再由队列读取代理读取并应用到发布服务器。它与分发代理方向相反,是“订阅→发布”的回传通道。若队列读取代理积压,订阅端的更新会长时间停留在队列中,表现为发布端看不到订阅端的修改。

三、代理配置文件(Agent Profile)

代理配置文件是一组预定义的参数集合,用于统一控制代理行为,避免逐个作业手工调整。SQL Server 为每类代理提供默认配置文件,例如分发代理的默认配置文件包含 CommitBatchSize=100、CommitBatchThreshold=1000、PollingInterval=10 等。可以基于默认配置新建自定义配置文件,再通过 sp_add_agent_profile、sp_change_agent_profile 等存储过程或 SSMS 图形界面把配置文件绑定到具体代理作业。

配置文件的实用价值在于“批量调优”:例如为跨广域网的拉取订阅创建低带宽配置文件,把 CommitBatchSize 调小、PollingInterval 调大;为高吞吐内网推送订阅创建高吞吐配置文件,把批大小调大。修改配置文件后,需要重启对应代理作业才能生效。

四、作业调度管理

每个代理都对应一个 SQL Server 代理作业,作业步骤调用 replmerg.exe、distrib.exe、logread.exe、snapshot.exe、qreader.exe 等可执行文件。调度方式主要有三种:

  • 连续运行:作业计划设为“启动时自动启动”,代理常驻,适合事务复制的日志读取和分发代理。
  • 按计划运行:如每 15 分钟运行一次,适合合并复制或对延迟不敏感的订阅。
  • 按需运行:手动启动,常用于快照代理重新初始化。

调度管理要关注两个指标:一是延迟,即发布端提交到订阅端可见的时间差;二是积压,可通过分发数据库的 MSdistribution_history、MSrepl_commands 未分发命令数,或复制监视器(Replication Monitor)的“未分发的命令”计数器观察。若日志读取代理正常但分发代理长时间空闲,通常说明没有新命令或分发代理未启动;若未分发命令持续增长,则说明分发代理处理能力不足或订阅端写入受阻。

排查顺序建议:先看复制监视器中各代理的“状态”和“上次同步时间”,再查分发数据库的未分发命令数,最后结合代理作业历史中的错误信息定位到具体代理。

五、一个可参考的调度配置示例

假设一个事务复制场景:发布端为订单库,订阅端为报表库,要求延迟不超过 30 秒,网络为内网千兆。可参考如下配置:

代理调度关键参数说明
快照代理按需默认初始化时手动运行
日志读取代理连续PollingInterval=5,ReadBatchSize=500保证日志及时读取
分发代理连续CommitBatchSize=200,CommitBatchThreshold=2000平衡吞吐与延迟

该配置属于示例性建议,实际值需结合事务大小、订阅端写入能力和网络状况调整。调整后应观察 10~15 分钟内的未分发命令数和端到端延迟,确认没有出现命令积压或订阅端锁等待升高,再决定是否固化到自定义配置文件中。

掌握代理分工与调度后,后续排查复制延迟、数据不一致和作业失败时,就能快速判断问题出在“捕获”“传输”还是“应用”环节,而不是盲目重启所有作业。