資料未傳遞至訂閱者
如果發現資料並未傳送至「訂閱者」,可能有兩個廣泛原因:
由於篩選、代理程式問題或其他複寫錯誤而導致資料未套用。
資料在套用後於「訂閱者」端被刪除。
說明
導致資料無法傳遞至「訂閱者」的原因可能有以下幾種:
資料表已經篩選,沒有要傳遞至給定訂閱者的變更。
一或多個代理程式正在執行,或因錯誤而導致失敗。
已經初始化交易式訂閱 (不含快照集),並且已在建立發行集後於「發行者」上進行了變更。
交易式發行集的複寫預存程序執行,於訂閱者端產生不同的結果。
交易式發行項使用的 INSERT 預存程序包含不符合的條件。
資料被使用者、複寫指令碼或其他應用程式刪除。
資料被觸發程序或包含 ROLLBACK 陳述式的觸發程序刪除。
使用者動作
嘗試診斷資料無法傳遞給「訂閱者」的原因時,建議您使用驗證或 tablediff 公用程式以確認未遺漏資料列:
若可以執行散發代理程式或合併代理程式,請執行二進位總和檢查碼驗證,以決定是否遺漏資料。您亦可使用資料列計數驗證,但這種方法無法顯現資料內容的差異。如需詳細資訊,請參閱<驗證複寫的資料>。
如果「散發代理程式」或「合併代理程式」無法執行,則透過執行 tablediff 公用程式來判斷資料是否遺漏。如需有關在複寫資料表上使用此公用程式的資訊,請參閱<如何:比較複寫資料表的差異 (複寫程式設計)>。
查找資料遺漏的原因
下列動作可處理「解釋」一節列出的原因:
資料表已經篩選,沒有要傳遞至給定訂閱者的變更。
「訂閱者」端的資料列遺漏可能無法複寫,這是因為它們不符合發行集的篩選條件。所有類型的複寫均支援靜態篩選,除此之外,合併式複寫還支援參數化篩選與聯結篩選。如需詳細資訊,請參閱<篩選發行的資料>。如果篩選發行集中的一或多個發行項,請執行下列程序並確認篩選子句的值:
快照式和交易式發行集的靜態篩選:由 sp_helparticle (Transact-SQL) 傳回的 filter_clause 資料行。
合併式發行集的靜態篩選或參數化篩選:由 sp_helpmergearticle (Transact-SQL) 傳回的 subset_filterclause 資料行。
合併式發行集的聯結篩選:由 sp_helpmergefilter (Transact-SQL) 傳回的 join_filterclause 資料行。
使用篩選子句來判斷遺漏的資料列是否符合篩選條件。例如,您可以對「發行者」端的資料表執行篩選子句,以判斷傳回的資料是否與「訂閱者」端的資料相符。
一或多個代理程式正在執行,或因錯誤而導致失敗:
如果您要初始化訂閱,請確定在嘗試使用「散發代理程式」或「合併代理程式」套用快照集之前,發行集的「快照集代理程式」已完成。如果您嘗試在代理程式完成前套用快照集,將出現下列錯誤:「發行集 '%s' 的初始快照集還無法使用」。
對於交易式複寫,請確定「分散代理程式」與「記錄讀取器代理程式」正在執行;對於合併式複寫,請確定「合併代理程式」正在執行。如需啟動這些代理程式的詳細資訊,請參閱<如何:啟動和停止複寫代理程式 (SQL Server Management Studio)>和<複寫代理程式可執行檔概念>。
如果代理程式因錯誤而停止,請檢視代理程式的錯誤詳細資料,以確定基本原因。如需檢視「快照集代理程式」和「記錄讀取器代理程式」之錯誤詳細資料的資訊,請參閱<如何:檢視與發行集相關聯之代理程式的資訊並執行工作 (複寫監視器)>。如需「散發代理程式」和「合併代理程式」的詳細資訊,請參閱<如何:檢視與訂閱相關聯之代理程式的資訊並執行工作 (複寫監視器)>。若錯誤繼續發生,請增加代理程式的記錄,並指定記錄的輸出檔。視錯誤內容的不同,可提供導致錯誤的步驟和 (或) 其他錯誤訊息。如需詳細資訊,請參閱<複寫代理程式 (疑難排解)>。
導致資料無法傳遞的常見錯誤包括權限問題與強制違規。如需權限問題的詳細資訊,請參閱<安全性問題是防止資料被複寫>。強制違規可防止在「訂閱者」端插入資料列。
針對交易式複寫,違反條件約束會視為錯誤;若發生此情況,依預設會導致散發代理程式停止同步處理 (如需更多有關略過錯誤的資訊,請參閱<略過交易式複寫中的錯誤>)。針對合併式複寫,違反條件約束會視為衝突;這些衝突會記錄下來,但並不會導致合併代理程式停止同步處理。針對兩種複寫類型,若在某節點成功插入、更新或刪除,但在另一節點失敗了,則違反條件約束可能導致無法聚合。
在發行資料表時,預設結構描述選項指定外部索引鍵條件約束以及檢查條件約束應使用 NOT FOR REPLICATION 選項集,建立在訂閱資料庫中。若您的應用程式需要不同的條件約束設定,請變更結構描述選項。如需詳細資訊,請參閱<如何:指定結構描述選項 (SQL Server Management Studio)>和<如何:指定結構描述選項 (複寫 Transact-SQL 程式設計)>。
已經初始化交易式訂閱 (不含快照集),並且已在建立發行集後於「發行者」上進行了變更:
如果您啟用從備份初始化發行集,一旦建立發行集,系統便會在發行集資料庫中追蹤已發行資料表的變更。初始化訂閱後,只要暫止的變更仍位於散發資料庫中,即可將其傳遞至「訂閱者」。
與從備份初始化不同,如果您使用僅支援複寫選項來初始化訂閱,您或您的應用程式必須確定資料和結構描述在您新增訂閱時已正確進行了同步處理。例如,若在複製資料和結構描述到訂閱者的時間,與加入訂閱的時間之間,發行者端有活動,此活動所導致的變更可能不會複寫到訂閱者。
如需詳細資訊,請參閱<不使用快照集初始化交易式訂閱>。
交易式發行集的複寫預存程序執行,於訂閱者端產生不同的結果。
若您複寫預存程序的執行,程序定義會在訂閱初始化之後,複寫到訂閱者端;在發行者端執行程序時,複寫會在訂閱者端執行對應程序。如需詳細資訊,請參閱<在交易式複寫中發行預存程序執行>。
若預存程序在訂閱者端執行其他動作,或者針對發行者以外的其他資料作業,則可能無法聚合。考慮使用執行計算的程序,然後根據此計算插入資料。若訂閱者已篩選,以至於訂閱者端的計算皆以其他資料為基礎,那麼插入訂閱者端的結果會有所不同,或者根本不會進行插入。
交易式發行項使用的 INSERT 預存程序包含不符合的條件。
依預設,交易式複寫使用一組預存程序以將變更傳播至「訂閱者」。您也可以自訂這些程序以包括應用程式所需的商務邏輯。如需詳細資訊,請參閱<指定交易式發行項變更的傳播方式>。如果 INSERT 預存程序在其邏輯中包含不相符的條件,則不會發生插入。在允許對其他資料表 (資料表 B) 進行插入之前,請考慮使用自訂為檢查資料表 (資料表 A) 中特定值的程序。如果因發生錯誤或資料尚未複寫至資料表 A 而導致該資料表中的值不可用,則資料表 B 中將遺漏預期的資料列。
資料正被使用者、複寫指令碼或其他應用程式刪除:
如果您要允許使用者在「訂閱者」端刪除資料,請使用合併式複寫、具有可更新訂閱的交易式複寫或點對點交易式複寫。刪除將傳播至「訂閱者」,因此「發行者」端與「訂閱者」端的資料最終將聚合。如需詳細資訊,請參閱<合併式複寫概觀>和<交易式複寫的發行集類型>。
如果您要防止使用者在「訂閱者」端刪除資料,請為每個包含 ROLLBACK 字並使用 NOT FOR REPLICATION 選項的資料表建立觸發程序 (防止在複寫代理程式執行作業時引發觸發程序)。例如:
USE AdventureWorks GO CREATE TRIGGER prevent_user_dml ON Person.Address FOR INSERT, UPDATE, DELETE NOT FOR REPLICATION AS ROLLBACK
如需詳細資訊,請參閱<CREATE TRIGGER (Transact-SQL)>和<使用 NOT FOR REPLICATION 控制條件約束、識別和觸發程序>。
複寫可讓您在套用快照集前後以及同步處理期間執行指令碼。sp_addpublication 和 sp_addmergepublication 的 @pre_snapshot_script 與 @post_snapshot_script 參數可允許您指定在套用快照集之前和之後要執行的指令碼。如需詳細資訊,請參閱<在套用快照集的前後執行指令碼>。預存程序 sp_addscriptexec 可允許您在同步處理時執行指令碼。如需詳細資訊,請參閱<如何:在同步處理期間執行指令碼 (複寫 Transact-SQL 程式設計)>。
這些指令碼通常用在管理工作,如在訂閱者端加入登入。如果在「訂閱者」端使用指令碼來刪除應視為唯讀的資料,則管理員必須確定不會導致非聚合。
資料正被觸發程序或包含 ROLLBACK 陳述式的觸發程序刪除。
必須適當管理訂閱者的觸發程序,以免造成無法聚合或其他問題:
若您使用合併式複寫、可更新訂閱交易式複寫或點對點交易式複寫,觸發程序應只在訂閱者端造成資料變更。如需詳細資訊,請參閱<合併式複寫概觀>和<交易式複寫的發行集類型>。
在多數情況下,觸發程序應使用 NOT FOR REPLICATION 選項。若觸發程序包含 ROLLBACK 陳述式,且觸發程序未使用 NOT FOR REPLICATION 選項,則可能無法套用複寫到訂閱者的資料列。
針對交易式複寫,還有關於 XACT_ABORT 設定和在觸發程序中使用 COMMIT 與 ROLLBACK 陳述式的其他考量。如需進一步資訊,請參閱<交易式複寫考量>中的「觸發程序」一節。