交易式複寫的可更新訂閱

[!附註]

未來的 Microsoft SQL Server 版本將移除這項功能。請避免在新的開發工作中使用這項功能,並規劃修改目前使用這項功能的應用程式。

交易式複寫透過可更新訂閱和點對點複寫支援在訂閱者端的更新。以下是可更新訂閱的兩種類型:

  • 立即更新。發行者和訂閱者必須連接,以便更新訂閱者端的資料。

  • 佇列更新。發行者和訂閱者不必連接,即可更新訂閱者端的資料。更新可在訂閱者或發行者離線時進行。

當資料在訂閱者端更新時,它會先傳播至發行者,然後再傳播至其他訂閱者。如果使用立即更新,則透過使用兩階段認可通訊協定,變更會立即傳播。如果使用佇列更新,則變更會儲存於佇列中;然後,佇列交易會在網路連接可用時,在發行者端上非同步套用。因為更新會非同步地傳播到「發行者」,因此相同的資料可能已經被「發行者」或另一個「訂閱者」更新過,所以在套用更新時可能會出現衝突。衝突會偵測出來,並且根據建立發行集時設定的衝突解決原則來解決。

如果在「新增發行集精靈」中建立具有可更新訂閱的交易式發行集,則會啟用立即更新和佇列更新。如果以預存程序建立發行集,則可啟用一個或兩個選項。建立發行集的訂閱時,則需指定要使用的更新模式。必要時,可切換更新模式。如需詳細資訊,請參閱下面的<切換更新模式>一節。

啟用交易式發行集的可更新訂閱

建立交易式發行集的可更新訂閱

切換更新模式

使用可更新訂閱時,可以指定訂閱應使用一個更新模式,如果應用程式有所要求,再切換至另一個更新模式。例如,您可以指定訂閱應使用立即更新,但是如果系統錯誤造成失去網路連接,則切換至佇列更新。

[!附註]

複寫不會自動切換更新模式。您必須透過 SQL Server Management Studio 設定更新模式,或者您的應用程式必須呼叫 sp_setreplfailovermode (Transact-SQL) 來切換模式。

如果從立即更新切換至佇列更新,則在「訂閱者」和「發行者」連接,且「佇列讀取器代理程式」將佇列中所有暫止訊息套用至「發行者」之前,無法切換回立即更新。

切換更新模式

若要切換更新模式,則必須啟用兩種更新模式的發行集和訂閱,然後必要時在它們之間進行切換。

使用可更新訂閱之考量

一般考量

  • 執行 MicrosoftSQL Server 2000 SP3 和更新版本的「訂閱者」支援更新訂閱。

  • 在更新訂閱或佇列更新訂閱啟用發行集後,則無法停用該發行集的選項 (雖然訂閱不需要使用該選項)。若要停用該選項,則必須刪除發行集並建立一個新的發行集。

  • 不支援重新發行資料。

  • 複寫將 msrepl_tran_version 資料行加入已發行的資料表中,用來進行追蹤。由於此附加資料行的原因,所有 INSERT 陳述式應包含資料行清單。

  • 若要在支援更新訂閱的發行集之資料表中進行結構描述變更,則必須停止「發行者」和「訂閱者」上所有資料表的活動,且暫止資料變更必須在進行任何結構描述變更前傳播至所有節點。這會確保未處理完畢的交易不與暫止結構描述變更發生衝突。結構描述變更傳播至所有節點之後,可於已發行的資料表上繼續進行活動。如需詳細資訊,請參閱<如何:停止複寫拓撲 (複寫 Transact-SQL 程式設計)>。

  • 如果計劃切換更新模式,則「佇列讀取器代理程式」在訂閱初始化後必須至少執行一次 (依預設,「佇列讀取器代理程式」會持續執行)。

  • 如果「訂閱者」資料庫是水平分割,且在此分割中有存在於訂閱者端,而非在發行者端的資料列,則訂閱者無法更新這些已經存在的資料列。嘗試更新這些資料列會傳回錯誤。資料列應該從資料表刪除,然後在發行者端加入。

在訂閱者端的更新

  • 即使訂閱已過期或為非使用中,訂閱者端的更新也會傳播至發行者。請確定所有此類訂閱都已卸除或重新初始化。

  • 如果使用 TIMESTAMP 或 IDENTITY 資料行,且它們做為基底資料型別來複寫,則不應在訂閱者端上更新這些資料行中的值。

  • 訂閱者無法更新或插入 textntextimage 值,因為無法從複寫變更追蹤觸發器中插入或刪除的資料表中讀取它。同樣地,「訂閱者」無法使用 WRITETEXT 或 UPDATETEXT 更新或插入 text 或 image 值,因為資料已被「發行者」覆寫。相反地,您可以分割 textimage 資料行至其他不同的資料表,並在交易中修改這兩個資料表。

    若要在「訂閱者」端更新大型物件,則分別使用 varchar(max)nvarchar(max)varbinary(max) 資料類型,來取代 textntextimage 資料類型。

  • 不允許對產生重複項的唯一索引鍵 (包含主索引鍵) 進行更新 (例如格式為 UPDATE <column> SET <column> =<column>+1 的更新),並且會由於違反唯一性而被拒絕。這是因為在「訂閱者」端進行的設定更新,會做為每個受影響之資料列的個別 UPDATE 陳述式由複寫進行傳播。

  • 如果「訂閱者」資料庫是水平分割,且在此分割中有存在於「訂閱者」端,而非在「發行者」端的資料列,則「訂閱者」無法更新這些已經存在的資料列。嘗試更新這些資料列會傳回錯誤。資料列應該從資料表刪除,然後再次插入。

使用者自訂觸發程序

  • 如果應用程式在「訂閱者」端需要觸發器,則該觸發器應以「發行者」和「訂閱者」端的 NOT FOR REPLICATION 選項進行定義。如需有關這個選項的詳細資訊,請參閱<使用 NOT FOR REPLICATION 控制條件約束、識別和觸發程序>。這會確保觸發器僅為原始資料變更而引發,而不會在複寫變更時引發。

  • 請確保複寫觸發器更新資料表時不會引發使用者自訂的觸發器。這可透過呼叫使用者自訂觸發器主體中的 sp_check_for_sync_trigger 程序來完成。如需詳細資訊,請參閱<sp_check_for_sync_trigger (Transact-SQL)>。

立即更新

  • 對於立即更新訂閱,「訂閱者」端的變更會傳播至「發行者」,並使用「Microsoft 分散式交易協調器」(MS DTC) 來套用。請確定已在「發行者」和「訂閱者」端安裝並設定了 MS DTC。如需詳細資訊,請參閱 Windows 文件集。

  • 立即更新訂閱使用的觸發器要求連接到「發行者」以複寫變更。如需設定此連接安全性的詳細資訊,請參閱<更新訂閱的安全性考量>。

  • 如果發行集允許立即更新訂閱,且發行集中的發行項具有資料行篩選,則無法篩選無預設值的不可為 Null 資料行。

佇列更新

  • 包含在合併式發行集的資料表也無法發行為允許佇列更新訂閱的部分交易式發行集。

  • 在使用佇立更新時,不建議更新主索引鍵資料行,這是因為主索引鍵是所有查詢的記錄定位器。若衝突解決原則是設為「訂閱者優先」,則應在更新主索引鍵時多加注意。若「發行者」與「訂閱者」的主索引鍵均更新,則結果將會是有著不同主索引鍵的兩資料列。

  • 對於資料類型為 SQL_VARIANT 的資料行:當「訂閱者」端插入或更新資料後,該資料會在從「訂閱者」複製到佇列之時,由「佇列讀取器代理程式」以下列方式進行對應:

    • BIGINT、DECIMAL、NUMERIC、MONEY 和 SMALLMONEY 對應至 NUMERIC。

    • BINARY 和 VARBINARY 對應至 VARBINARY 資料。

衝突偵測與解決方案

  • 對於「訂閱者成功」衝突原則:至主索引鍵資料行的更新不支援衝突解決。

  • 複寫不會解決因外部索引鍵條件約束錯誤引起的衝突:

    • 如果衝突是非預期的且資料分割正常 (「訂閱者」不更新相同資料列),則可使用「發行者」和「訂閱者」上的外部索引鍵條件約束。

    • 如果預期會發生衝突:在使用「訂閱者成功」衝突解決時,不應使用發行者或訂閱者端的外部索引鍵條件約束;在使用「發行者成功」衝突解決時,不應使用訂閱者端的外部索引鍵條件約束。