當Transaction Replication 發佈端的資料表更新或刪除某筆記錄時,原則上會通知訂閱端的資料表更新或刪除某筆資料(假設我們的Replication 是push 機制)
反過來看,若訂閱端的資料表內容被使用者或其他AP異動過,則發佈端進行更新或修改資料時,通知訂閱端同步異動資料時找不到這筆資料。則會發生下列錯誤訊息。(下圖模擬的錯誤畫面為,訂閱端的記錄先行刪除了,因此執行複寫的刪除預存程序,傳回受影響記錄筆數 0,引發錯誤):
開啟效能監視器,切換至All Subscription畫面,檢視錯誤訊息(上圖)。
在Subscriton的錯誤細節中,取得錯誤編號如下圖所示
解法一
Step1:根據上圖提供的交易序號(Transaction sequence number xact_seqno)和命令識別碼(Command ID command_id)搭配 Distribution 系統資料庫內的 sp_browsereplcmds 系統預存程序,或是直接查詢 MSrepl_commands 系統資料表。(註:此查詢,要用 文字顯示,而非 grid,且參數是數值型,轉成文字會變成亂碼)
select command_id,
CONVERT(nvarchar(max),case when datalength(command) > 6 then right(command,datalength(command)-6) else command end),command
from distribution.dbo.MSrepl_commands
where xact_seqno=0x0000023C0000172000040000000 and command_id=1
執行結果如下:
command_id
----------------------------------------------------------------------------------------------------------------------------------------------
C A L L [ d b o ] . [ s p _ MSdel_dbotblMapKsDetail]
( ? , ? , ? , ? , ? , ? , ? , ? , ? ) } 162 04 B2 699 0x7A00000009007B00430041004C004C0020005B00640062006F005D002E005B00730070005F004D005300640065006C005F00640062006F00740062006C004D00610070004B007300440065007400610069006C005D00200028003F002C003F002C003F002C003F002C003F002C003F002C003F002C003F002C003F0029007D00
Step2:執行以下的預存程序(要初始化的個別資料表不大,整個Publication也不大的情況下)
exec distribution.dbo.sp_browsereplcmds
@xact_seqno_start = '0x0000023C000010BF000800000000',
@xact_seqno_end = '0x0000023C000010BF000800000000'
執行結果如下圖所示。在cmmand欄位可發現 Transaciton replication 發佈端所觸發的執行語法,應在訂閱端執行成功卻失敗的指令。
以本例來看,是因為訂閱端有三筆資料先行被刪除,因此使用下列步驟中的 Iinsert 指令,先將訂閱端簡單恢復。
主要目的是讓讓Distribution Agent可以正常執刪除指令。
Step3
insert into dbo.tblMapKsDetail(companyID,AcctCtrl1,AcctCtrl2,AcctCtrl3,AcctCtrl4,
AcctCtrlNo1,AcctCtrlNo2,AcctCtrlNo3,AcctCtrlNo4)
values('162','04','B2',' ',' ','699','','','',0,0,0,0,GETDATE()),
('162','04','B2',' ',' ','721','','','',0,0,0,0,GETDATE()),
('162','04','B2',' ',' ','848','','','',0,0,0,0,GETDATE())
- 解法二
若資料表內容複雜,不想要個別修改紀錄,而從 Publisher 初始化該資料表,但又不影響整個 Publication 所有的資料表,可以執行以下的預存程序(要初始化的個別資料表不大,整個Publication也不大的情況下)
--要在提供 Publication 的資料庫下執行,而非 Distribution
exec sp_reinitsubscription
@publication = 'test',
@article ='t',
@subscriber ='P714P4USER',
@destination_db ='d',
@for_schema_change =1,
@invalidate_snapshot =1
--產生 Snapshot
--這會產生整個 publication 的,但Distributor會僅對上述標示要 Initialize 的資料表
--利用 snapshot 執行個別資料表的初始化,這可以從 UI 做
EXEC sp_startpublication_snapshot @publication='test'
留言列表