一个香港客户的现网系统,按照客户的需求,我们为他配置和安装了SQL Server的分发订阅功能。实际环境则为:主数据中心位于香港跑马地的总部,运行着MAMDB,DYACDB两个数据库,需要将这两个数据库的数据实时进行同步到位于沙田的分支数据中心,假设跑马地的数据库名称为DB,沙田的分支数据中心名称为BAK的话。实际上就是DB实时将数据传送到BAK上进行同步,保证业务的连续性。
在正常运行了一段时间之后,某天DB数据库报“The row was not found at the Subscriber when applying the replicated command”这个错误,同时会看到有很多的“
SQL Agent The semaphore timeout periodhas expired。”和“[000] Request to run job refused because the job is already running>from a request by Start Sequence 0”
这两条错误将我的注意力一直集中在是否是分发订阅服务出了错误上面。从后两条报错来看,很像是基础网络环境除了问题,但是香港的互联网建设还是很不错的,长时间从跑马地Ping沙田,延时一直都很低。
真的很奇怪,到底是什么原因。
仔细去查看日志,发现一条名叫20598的错误,这是一个很重要的线索。我们需要看看20598该如何处理,Google了一下相关资料,发现尝试输入语句:
USE distribution
02.
03.
go
04.
05.
SELECT
*
06.
FROM
dbo.msarticles m
07.
WHERE
EXISTS (
SELECT
mc.article_id
08.
FROM
msrepl_commands mc
09.
WHERE
mc.xact_seqno = 0x00000022000000480003XXXXXXX
10.
AND
mc.article_id = m.article_id)
11.
12.
EXEC
Sp_browsereplcmds
13.
@xact_seqno_start =
'0x00000022000000480003XXXXXXX'
,
14.
@xact_seqno_end =
'0x00000022000000480003XXXXXXX'
发现出现问题的GUID号码和相关的数据库名,进入到这个数据库,终于找到了指定的条目记录:
那么为什么会造成此现象呢?查询了一些资料发现:
根本原因是备库出现了人为手动删除的动作。
如果原始数据库是这样的:
DB-1 INT
id log id log
1 A 1 A
2 B 2 B
3 C 3 C
这是理想状态,当人为操作备库,删除id=1的记录后,变成这样:
DB-1 INT
id log id log
1 A 2 B
2 B 3 C
3 C
如果DB-1中id=1的条目发生变化为X,同时又新建了一个条目变成
DB-1 INT
id log id log
1 X 2 B
2 B 3 C
3 C
4 D
分发订阅功能会发出两条指令给INT备库,即:Insert 4,D 以及 Update 1,X
注意这里是Update,而不是Insert!所以系统会报找不到id=1的行。
通过与研发确认:
COM_OPERATEBIFORSYN是触发器插入的记录,插入后会被同步程序处理并删除,确实可能导致再同步删除消息时,备库中已经没有该记录而失败,现场已经能够复现该问题。
问题终于得到有效定位,并开始着手解决。
总结起来:
1。按图索骥,不能着急。
2。对自己要有信心,这期间冷嘲热讽,不信任的声音一直在周围聒噪,当问题当面锣,对面鼓的摆出来时,这群傻逼都要给老子闭嘴!
3。任何问题的定位和解决,拿出证据,并说服别人才是硬道理!