3. 复制代理体系与作业调度
SQL Server 复制的“自动化”并不是一个进程包办所有事情,而是由一组职责单一的代理(Agent)分工协作完成。理解每个代理“读什么、写什么、什么时候被唤醒”,是排查复制延迟、数据不一致和作业失败的基础。本节先建立代理协作的整体视图,再逐一说明各代理的职责边界、关键参数与作业调度管理方式。
一、代理协作的整体视图
复制拓扑中,发布服务器、分发服务器和订阅服务器之间通过分发数据库(distribution)解耦。发布服务器上的变更先被捕获并写入分发数据库,再由分发代理推送到订阅服务器。不同复制类型使用的代理组合不同:
- 快照复制:快照代理 + 分发代理。
- 事务复制:快照代理(初始化)+ 日志读取代理 + 分发代理;若使用排队更新订阅,还会涉及队列读取代理。
- 合并复制:快照代理 + 合并代理;合并代理同时承担变更上传与下载。
下图给出事务复制(含排队更新)场景下各代理与数据库对象之间的数据流关系,可作为后续排查的定位地图。
二、各代理的职责与关键行为
快照代理负责生成初始数据集。它连接发布数据库,对已发布表加锁(默认使用并发快照,减少阻塞),将数据以 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 分钟内的未分发命令数和端到端延迟,确认没有出现命令积压或订阅端锁等待升高,再决定是否固化到自定义配置文件中。
掌握代理分工与调度后,后续排查复制延迟、数据不一致和作业失败时,就能快速判断问题出在“捕获”“传输”还是“应用”环节,而不是盲目重启所有作业。