SQL Server 同步复制中的MSSQL_REPL2147201001問題處理

引述


先,说我为什么写这篇文章,它让你了解到什么,对你是否有帮助。要是你是刚接触SQL Server同步复制,那么你可能会碰到各种各样的问题,你可能不会从哪里入手解决,或者你从Baidu,Google上找到解决问题的方法,但你很多时候只看到别人说的答案,很少有人去写分析其中的原因,倘若你没有找其他资料或查阅帮助文档了解为什么,以后你碰到同样问题,你也只能照搬之前的答案,有时候碰巧正确,你会突然的喜悦,但始终你不知道为什么那样,正如我们在学校学习,说的知其然而不知其所以然。

回到主题,以下内容使用我记录的繁体笔记,测试环境是SQL Server 2005 (SP3) ,因时间原因,没有作简体转换,如有哪一朋友需要,我可以测试个简体的版本放上来。无论如何,如果你有什么意见和见解,可以通过文章后面的发布评论与我交流,或者通过Email方式,与我交流。我Email是:glal@163.com

問題描述


在合併式複製,當初始化訂閱時候,發生了錯誤,圖示:

dfg

錯誤信息,文字描述如下:

嘗試執行的命令:
{call sp_MSsetconflicttable (N'Product', N'MSmerge_conflict_ReplicationDB-Merge_Product', N'PC143\SQL2005DE2', N'ReplicationDB', N'ReplicationDB-Merge')}
錯誤訊息:
•    接近 'ProductID' 之處的語法不正確。 (來源: MSSQLServer,錯誤號碼: 102)
取得說明:
http://help/102
•    合併處理無法將快照集傳遞給訂閱者。如果使用 Web 同步處理,可能是合併處理無法建立或寫入訊息檔。執行疑難排解時,請使用詳細資訊歷程記錄來重新啟動同步處理,並指定寫入的輸出檔。 (來源: MSSQL_REPL,錯誤號碼: MSSQL_REPL-2147201001)
取得說明:
http://help/MSSQL_REPL-2147201001

問題分析


從MSDN的聯機幫助文檔中,查詢到SQL Server 2008 R2版本錯誤編碼MSSQL_REPL-2147201001的描述信息:

說明

XML 訂閱者的 COM 物件初始化失敗。合併式複寫為何未能將結構描述變更套用到訂閱者的某些原因包括以下項目:

· 建立目錄來寫入暫時快照集檔案時,可能發生了失敗狀況。

· 列舉結構描述發行項時,可能發生了失敗狀況。

· 對於 SQL Server Compact 訂閱者而言,重新初始化訂閱時可能發生了失敗狀況。

· 如果物件是以訊息為根據,則表示寫入訊息檔案時可能發生了失敗狀況。

使用者動作:

執行 SQL Server Profiler 並檢查 replmerg.log 看看是否有失敗狀況。如果您正在使用 Web 同步處理,請提高 websync 記錄檔的嚴重性、重新執行此案例,然後檢查 websync.log 檔案中的錯誤。

如果您正在使用 Web 同步處理,可以啟動 Replmerg.exe 並傳遞 -T 106 選項來使用追蹤旗標 106。如此可讓您看到送給發行者以及發行者所傳送的訊息。代理程式會藉由將追蹤旗標新增到 Replmerg.exe 代理程式命令列,將用戶端的輸入訊息寫入到名為 ExchangeID(guid).IN.XML 的檔案中,並將輸出訊息寫入到名為 ExchangeID(guid).OUT.XML 的檔案中 (在這些檔案名稱中,guid 是 Exchange Server 工作階段的 GUID)。這些檔案會建立在之前叫用 Replmerg.exe 的目錄中。為了安全性起見,您應該在完成之後刪除這些檔案。

在SQL Server 2005版本上找不到對應的解決方法。然而,上面說一點“列舉結構描述發行項時,可能發生了失敗狀況”,可以從發行數據庫和訂閱數據庫的表結構上分析。

原始表Product結構:

Create Table Product

(

ProductID uniqueidentifier Not Null Default(Newid()),

Name nvarchar(50) Not null,

ProductNumber nvarchar(50) Not null,

Constraint PK_Product_ProductID Primary Key(ProductID Asc)

)

發行數據庫上的表Product結構:

CREATE TABLE [dbo].[Product](

[ProductID] [uniqueidentifier] NOT NULL DEFAULT (newid()),

[Name] [nvarchar](50) NOT NULL,

[ProductNumber] [nvarchar](50) NOT NULL,

[rowguid] [uniqueidentifier] ROWGUIDCOL NOT NULL CONSTRAINT [MSmerge_df_rowguid_C03B37723F2840DAB64E7E25AB0AECBC] DEFAULT (newsequentialid()),

CONSTRAINT [PK_Product_ProductID] PRIMARY KEY CLUSTERED

(

[ProductID] ASC

)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]

) ON [PRIMARY]

這裡可以發行在發行數據庫中表Product多了一個字段rowguid.而且設置了ROWGUIDCOL屬性,標誌唯一識別碼。根據猜測,rowguid這裡可能導致了初始化出問題。我們來看發行項的屬性設置:

如果表名稱使用中,則採取刪除數據的方式處理。問題可能出現在這裡了,在發行數據庫中表Product多字段rowguid,應用與合併複寫,而這裡初始化時候,插入數據前沒有創建rowguid字段導致資料列不一致,從而發生錯誤。

提示:
名稱為 rowguid 的資料行會加入到每個已發行的資料表中,除非該資料表中已含有設定了 ROWGUIDCOL 屬性之資料類型 uniqueidentifier 的資料行 (在此狀況下會使用此資料行)。rowguid 資料行用來唯一識別每個已發行資料表中的每個資料列。若從發行集卸除資料表,rowguid 資料行會遭到移除;若現有資料行用來進行追蹤,則不會移除資料行。

問題解決


接下來,就是根據上面分析的結果 ,去把問題給解決。下面從三個方面去解決。

1、在訂閱數據庫中表Product增加字段guid,并加入rowguidcol屬性。

Alter Table Product Add rowguid uniqueidentifier rowguidcol Default(newsequentialid())

2、刪除當前的訂閱和發行集,重新設置合併複製,在發行項屬性中“如果名稱使用,則採用”選項,選擇“卸除現有物件重建立新物件”。

dffff2

3. 刪除當前的訂閱和發行集,在發行數據庫和訂閱數據庫中的表Product表字段ProductID,加入ROWGUIDCOL屬性。

Alter Table Product alter Column ProductID Add rowguidcol

然後重新設置合併複製,在發行項目中“如果名稱使用,則採用”,根據實際需要選擇其中一種方式。

提示:
根據實際的環境選擇其中一種解決方法。如果要求處理問題速度,可以採用第1中處理方法,個人建議使用第3種解決方法。還有,在發行項屬性中“如果名稱使用,則採用”選項,選擇“卸除現有物件重建立新物件”時,特別要注意是其他表有外鍵關聯,和與它有關聯的含(WITH SCHEMABINDING)的視圖(View),否則會導致無法卸除物件(Drop Table).



之前,我也记录过类似这篇的同步复制中一问题的解决方法《可更新订阅的事务复制错误:列名 'msrepl_tran_version' 无效》,http://www.cnblogs.com/wghao/archive/2011/05/10/2041714.html
 
 
原文地址:https://www.cnblogs.com/wghao/p/2049497.html