在復制中,有的時候會出現訂閱端被人修改,導致發布端插入數據的時候主鍵沖突,這個時候我們要做的不是直接的初始化太過暴力,而對於生產環境來說,這樣的操作代價也會很大。下面會說幾種方法來處理沖突:
1、 查看出錯的復制命令的具體內容
如果在復制監視器的訂閱詳細信息中查看分發代理出錯信息時,如果發錯發生在應用復制命令時,則可以看到類似信息:
嘗試的命令:
If @@TRANCOUNT > 0 rollback tran
(事務序列號:.......)
錯誤消息:
違反了primary key 約束'%s'。不能在對象'%S'中插入重復鍵.
如下例子:
嘗試的命令: if @@trancount > 0 rollback tran (事務序列號: 0x0001D2A8000005D4002700000000,命令 ID: 2) 錯誤消息: Violation of PRIMARY KEY constraint 'PK_SOMasterExtention'. Cannot insert duplicate key in object 'dbo.SOMasterExtention'. The duplicate key value is (600001). (源: MSSQLServer,錯誤號: 2627) 獲取幫助: http://help/2627 Violation of PRIMARY KEY constraint 'PK_SOMasterExtention'. Cannot insert duplicate key in object 'dbo.SOMasterExtention'. The duplicate key value is (600001). (源: MSSQLServer,錯誤號: 2627) 獲取幫助: http://help/2627
在上面我們可以看到事務的序列號為 : 0x0001D2A8000005D4002700000000 ,而沖突主鍵為: 600001 ,但有的時候這個主鍵會不准確,當多個的時候也只是會顯示插入的第一個主鍵。
我們可以通過以下語句來看一下有多少的事務
use distribution go sp_browsereplcmds '0x0001D2A8000005D4002700000000' ,'0x0001D2A8000005D4002700000000'
可以看到以下結果:
由上面可以看到是8條插入語句在發布庫執行。command 默認的命名規則是sp_MS+operation+schemaName+tableName ,可以通過下面這個查詢定位到具體表
DECLARE @article_id int SET @article_id = 3 USE distribution GO SELECT * FROM MSarticles WHERE article_id=@article_id
可以看到
解決方法是將刪除的行在訂閱中重新插入,主鍵就是sp_MSins_dboSOMasterExtention里的參數。
如果在訂閱端刪除數據,而發布端又更新數據的時候,復制也會報錯,如下:
嘗試的命令: if @@trancount > 0 rollback tran (事務序列號: 0x0001D2A8000005DE001600000000,命令 ID: 1) 錯誤消息: The row was not found at the Subscriber when applying the replicated command. (源: MSSQLServer,錯誤號: 20598) 獲取幫助: http://help/20598 The row was not found at the Subscriber when applying the replicated command. (源: MSSQLServer,錯誤號: 20598) 獲取幫助: http://help/20598
2、 忽略復制失敗的命令
在復制監視器中可以選中發布服務器 ---在 "操作 '"下拉菜單中可以看到 "代理配置文件 "
可以看到代理配置文件屬性為:
可以在這個里面進行配置來設置跳過錯誤,也就是把默認設置改為" Continue on data consistency errors. " 如果設置之后沒有的話,可以把代理重新啟動。在此不再舉例了。
3、 比較表中的數據差異
使用sp_browsereplcmds 查詢復制出錯的語句並手工處理同步失敗會比較容易。但如果復制出錯誤的命令很多,則很難通過上述方法來解決。這種情況下,一般選擇忽略復制失敗的命令,然后比較發布表的訂閱表的數據差異來解決復制 。這個時候可以使用 tablediff 來對數據進行對比生成腳本。tablediff 具體的使用方法可以參看上一篇文章: http://www.cnblogs.com/zerocc/p/3233277.html 。
對於以上三種方式我提倡的是1和3,第二種方法不太提倡。