可更新訂閱 - 用於交易複製

適用於:SQL Server

注意

這項功能在 SQL Server 2012 到 2016 的版本中仍然受到支援。 SQL Server 的未來版本將移除此功能。 請避免在新的開發工作中使用這項功能,並規劃修改目前使用這項功能的應用程式。

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

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

  • 佇列式更新:Publisher 和 Subscriber 不必保持連線,也能在 Subscriber 端更新資料。 你可以在訂閱者或 Publisher 離線時更新資料。

當你在訂閱者那裡更新資料時,更新會先發送給 Publisher,然後再傳給其他訂閱者。 若使用即時更新,變更會立即透過兩階段提交協定完成。 如果您使用佇列式更新,變更會被放入佇列中。 當網路連線可用時,佇列中的交易會以非同步方式傳送至 Publisher。 由於更新是非同步傳送給 Publisher,相同的資料可能會由 Publisher 或其他訂閱者更新,且在套用更新時可能會發生衝突。 系統會根據您在建立出版品時設定的衝突解決政策偵測並解決衝突。

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

若要為交易式發行集啟用可更新的訂閱,請參閱 啟用交易式發行集的更新訂閱。

若要為交易性出版建立可更新訂閱,請參見 「建立可更新的交易出版訂閱(管理工作室)」。

切換更新模式

使用可更新訂閱時,你可以指定一種更新模式,若應用程式需要,則切換到另一種模式。 例如,你可以指定訂閱使用即時更新,但若系統故障導致網路連線中斷,則改為排隊更新。

注意

複製不會自動切換更新模式。 透過 SQL Server Management Studio 設定更新模式,或在應用程式中呼叫 sp_setreplfailovermode(Transact-SQL)來切換模式。

如果你從即時更新切換到排隊更新,必須等訂閱者與 Publisher 連接並由佇列讀取代理將佇列中所有待處理訊息套用給 Publisher 之前,才能切回即時更新。

切換更新模式

若要在更新模式之間切換,請為兩種更新模式都啟用發佈與訂閱,然後在必要時於兩者之間切換。 如需相關資訊,請參閱
切換可更新的交易式訂閱更新模式

使用可更新訂閱的考量

  • 啟用訂閱更新或排隊更新訂閱的出版品後,你無法關閉該出版品的選項(雖然訂閱者不一定需要使用)。 要停用這個選項,請刪除該出版物並建立一個新的。

  • 不支援重新發布資料。

  • 複寫會將 msrepl_tran_version 資料行新增至已發佈的資料表中,以供追蹤。 由於多了這個額外欄位,請在所有 INSERT 陳述式中加入欄位清單。

  • 若要在支援更新訂閱的出版資料表上進行結構變更,請在 Publisher 與 Subscribers 處停止該資料表的所有活動,並在進行任何架構變更前,將待處理的資料變更傳播至所有節點。 此流程確保未完成的交易不會與待處理的架構變更衝突。 當結構變更傳遍所有節點後,已發佈的資料表即可恢復活動。 如需詳細資訊,請參閱使複寫拓撲靜止化 (複寫 Transact-SQL 程式設計)。

  • 要在更新模式間切換,佇列讀取代理程式必須在訂閱初始化後至少執行一次(預設情況下,佇列讀取代理程式會持續執行)。

  • 如果訂閱者資料庫經過水平分割,且該分割區中的某些資料列存在於訂閱者端,但在發行者端不存在,則訂閱者無法更新這些原已存在的資料列。 嘗試更新這些資料列會傳回錯誤。 先從表格刪除這些列,然後在 Publisher 上新增。

  • 使用佇列式可更新訂閱者的交易式複寫,在使用唯一篩選索引時,效能可能會變慢。 如果在擁有唯一篩選索引的條目上發生衝突,衝突解決會導致訂閱者對未被唯一篩選索引涵蓋的資料列進行額外的刪除和插入。

訂閱者端的更新

  • 即使訂閱已過期或未啟用,訂閱者的更新仍會同步到發行者。 務必取消或重新初始化任何此類訂閱。

  • 如果你使用 TIMESTAMP 或 IDENTITY 欄位並將其複製為基礎資料型態,請不要在訂閱者頁面更新這些欄位的值。

  • 訂閱者無法更新或插入 文字、 ntext 或 影像 值,因為複製變更追蹤觸發器無法讀取已插入或刪除的資料表。 同樣地,訂閱者無法透過使用 WRITETEXT 或 UPDATETEXT 來更新或插入文字或圖片值,因為 Publisher 會覆蓋資料。 相反地,你可以將 文字 和 圖片 欄位分割到獨立的表格,並在交易中修改兩個表格。

    若要在訂閱者端更新大型物件,請分別以 varchar(max)、nvarchar(max) 和 varbinary(max) 資料類型取代 text、ntext 和 image 資料類型。

  • 對唯一鍵(包括主鍵)產生重複的更新,例如表單 UPDATE <column> SET <column> =<column>+1的更新,不被允許,且因唯一性違規而被拒絕。 在訂閱者端所做的集合式更新,會透過複寫針對每個受影響的資料列,以個別的 UPDATE 陳述式形式傳播。

  • 如果訂閱者資料庫經過水平分割,且該分割區包含存在於訂閱者端但不存在於發行者端的資料列,則訂閱者無法更新這些原有的資料列。 嘗試更新這些資料列會傳回錯誤。 刪除並重新插入這些列。

使用者自訂觸發程序

  • 如果應用程式需要在訂閱者端使用觸發程序,請在發行者和訂閱者端使用 NOT FOR REPLICATION 選項來定義這些觸發程序。 此選項確保觸發器僅在原始資料變更時觸發,且在複製傳遞變更時不會觸發。

    確保當複製觸發器更新資料表時,使用者定義的觸發器不會觸發。 在使用者定義的觸發器主體中呼叫程序 sp_check_for_sync_trigger 。 如需詳細資訊,請參閱 sp_check_for_sync_trigger (Transact-SQL)。

立即更新

  • 為了立即更新訂閱,訂閱者的變更會傳達給 Publisher,並透過 Microsoft Distributed Transaction Coordinator(MS DTC)來應用。 請確定已在「發行者」和「訂閱者」端安裝並設定了 MS DTC。 如需詳細資訊,請參閱 Windows 文件集。

  • 即時更新訂閱所使用的觸發條件需要與 Publisher 連接才能複製變更。

  • 如果出版品允許立即更新訂閱,且該刊物中的文章有欄位篩選功能,你無法在沒有預設值的情況下過濾掉不可空欄位。

排隊更新

  • 您不能將合併式發行集中包含的資料表,作為允許佇列更新訂閱之交易式發行集的一部分來發行。

  • 使用佇列更新時不要更新主鍵欄位,因為主鍵是所有查詢的記錄定位碼。 當衝突解決政策設定為訂閱者勝利時,更新主鍵時要謹慎。 如果 Publisher 和 Subscriber 都更新主鍵,結果是兩列不同的主鍵。

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

    • BIGINT、DECIMAL、NUMERIC、MONEY 和 SMALLMONEY 會對應到 NUMERIC。

    • BINARY 和 VARBINARY 對應為 VARBINARY 資料型別。

衝突偵測與解決

  • 關於訂閱者贏得衝突政策:衝突解決不支援主鍵欄位的更新。

  • 複製無法解決因外鍵約束失效而產生的衝突:

    • 如果你不預期衝突且資料分割得很好(訂閱者不會更新相同的列),就對 Publisher 和 Subscribers 使用外鍵約束。

    • 如果您預期會發生衝突,且使用「訂閱者獲勝」衝突解決機制,請不要在發行者 (Publisher) 或訂閱者 (Subscriber) 端使用外鍵約束。 如果您使用「發行者獲勝」衝突解決方式,請勿在訂閱者端使用外鍵條件約束。