SQLServer非默认端口下事务复制代理作业服务无法启动的处理
SQL Server事务复制的结构
SQLServer事务复制的架构如下:
1,实例层面:主要有发布服务器,分发服务器,订阅服务器三个服务器,其中发布服务器是数据源,分发服务器是数据的中转站,订阅服务器是数据的目的地
2,后台进程:主要有Snapshot Agent,Log Reader Agent,distrubution Agent三个进程组成,
Snapshot Agent负责对现有数据库生成快照,也即导出发布对象的内容(schema+data)到快照目录,该进程只会在发布创建后执行一次,一个发布对应一个Snapshot Agent服务,在下图中没有体现出来。
Log Reader Agent进程复制将发布端的事务日志解析成逻辑日志,推送到中转站,也即发布服务器(distribution),一个发布对应一个Log Reader Agent。
Distrubution Agent进程负责将发布服务器中的逻辑日志传送到目的地,也即订阅端,每个订阅分别对应一个Distrubution Agent服务。
以下测试场景使用三台服务器(SQL1作为publisher,SQL2作为distrubutor,SQL2,SQL3同时作为Subscriber),具体复制后台进程在distributor实例上,也即SQL2上的Agent中的Job如下所示:
另:SQLServer的事务复制模型与PostgreSQL的逻辑复制几乎完全一致,如果熟悉SQLServer的订阅发布复制模型,PostgreSQL的逻辑复制可以秒上手。
事务复制遇到非默认端口
通过SSMS创建完发布后,在创建订阅的过程中,如果订阅服务器的端口是非标端口,也即非默认的1433端口,在连接至订阅服务器是,用实例名+端口号的方式,可以正常连接,如下,完全没毛病。
以上操作生成的sql代码如下,生成的脚本中的@subscriber = N'SQL3,11433',与SSMS中的输入是一致的
-----------------BEGIN: Script to be run at Publisher 'SQL1'----------------- use [DB04] exec sp_addsubscription @publication = N'db04_publication', @subscriber = N'SQL3,11433', @destination_db = N'DB04', @subscription_type = N'Push', @sync_type = N'automatic', @article = N'all', @update_mode = N'read only', @subscriber_type = 0 exec sp_addpushsubscription_agent @publication = N'db04_publication', @subscriber = N'SQL3,11433', @subscriber_db = N'DB04', @job_login = null, @job_password = null, @subscriber_security_mode = 0, @subscriber_login = N'sa', @subscriber_password = null, @frequency_type = 64, @frequency_interval = 0, @frequency_relative_interval = 0, @frequency_recurrence_factor = 0, @frequency_subday = 0, @frequency_subday_interval = 0, @active_start_time_of_day = 0, @active_end_time_of_day = 235959, @active_start_date = 20240722, @active_end_date = 99991231, @enabled_for_syncmgr = N'False', @dts_package_location = N'Distributor' GO -----------------END: Script to be run at Publisher 'SQL1'-----------------
以上在SSMS中操作完全没有问题,当订阅创建完成之后,打开Replication Monitor查看复制状态的时候就开始报错了,一下用一个发布,创建了两个订阅,其中SQL2上的订阅是正常的,仅作为对比参考来说明问题缘由。
回到第一节中提到的事务复制相关的进程,其中这个出错的进程就是Distrubution Agent进程,也即从distribution服务器将逻辑日志往subscriber端推送的时候,distribution服务器连接subscriber时候失败,找到对应的Job后查看日志状态,日志显示:the process could not connect to Subscriber SQL3,11433。
首先可以确认的是,分发服务器到订阅服务器(SQL3,11433)之间的网络是通的,端口号也是通的,创建复制时输入的连接信息也是没有问题的,那它为什么就连不上呢?
事务复制相关的链接服务器
经过反复尝试之后,发现在创建订阅的时候,如果订阅服务器是非标端口,也即自定义端口,在创建的link server中会指定一个providerstring,这个与正常情况下创建的订阅(比如SQL2这个服务器)的link server 信息是不一致的。
通过别名映射到订阅服务器
经过查询发现,在SQLServer的replication中,如果是非标端口,需要再SSCM中定义一个别名(Aliases)作映射,也即在发布端创建一个订阅服务器的Server名称和一个端口号,重新映射成一个别名,然后在创建订阅的时候使用这个别名,可以规避上述问题。
在发布服务器上创建别名之后,重建创建订阅,事务复制开始恢复正常。
基于别名创建订阅之后,自动生成的连接服务器没有providersting
事务服务恢复正常。
吐槽
1,既然分发服务器无法直接通过非标端口连接到订阅服务器,那么在SSMS中创建订阅的过程中不报错,连接至订阅服务器的过程中正常,等创建完之后再报错。
2,SSMS的bug,运气太TM好了,刚好用到这个版本的SSMS,导致通过SSMS创建订阅的过程中频繁报错,如果没有意识到是SSMS的bug,你就无法想象当时的心情有多绝望。
3,SSMS在连接Replication Monitor的过程中,同样因为某些版本的bug,导致无法正常连接至Replication Monitor。
参考链接: