點對點 - 點對點複寫中的衝突偵測

適用於:SQL Server

點對點異動複寫可讓您在拓撲中的任何節點上插入、更新或刪除資料,以及讓資料變更傳播至其他節點。 由於您可以在任何節點上變更資料,因此不同節點的資料變更可能會彼此衝突。 如果在一個以上的節點上修改資料列,它可能會在此資料列傳播到其他節點時,造成衝突或甚至是遺失更新。

點對點複寫提供了可在點對點拓撲之間啟用衝突偵測的選項。 這個選項可避免因為未偵測到衝突所導致的問題,包括不一致的應用程式行為和遺失更新。 啟用這個選項時,預設會將衝突的變更視為造成散發代理程式失敗的嚴重錯誤。 在發生衝突時,此拓撲會維持不一致的狀態,直到解決衝突並讓拓撲之間的資料變成一致為止。

注意

若要避免潛在的資料不一致問題,請務必要避免發生點對點拓撲中的衝突,即使是啟用了衝突偵測也一樣。 若要確定只在一個節點上執行特定資料列的寫入作業,存取和變更資料的應用程式必須分割插入、更新和刪除作業。 這樣的分割可確保,從一個節點對給定資料列的修改會在其他節點修改該資料列之前,與拓撲中的所有其他節點同步處理。 如果應用程式需要複雜的衝突偵測與解決功能,請使用合併式複寫。 如需詳細資訊,請參閱合併式複寫偵測及解決合併式複寫衝突

了解衝突和衝突偵測

在單一資料庫中,由不同應用程式對相同資料列所做的變更不會導致衝突發生。 這是因為交易是序列化的,而且鎖定會處理並行的變更。 在非同步分散式系統 (例如點對點複寫) 中,交易會在每個節點上獨立運作,而且沒有任何機制可序列化多個節點之間的交易。 雖然您可以使用兩階段交易認可之類的通訊協定,但是這樣做會大幅影響效能。

在點對點複寫等系統中,當系統在個別對等中認可變更時,無法偵測衝突。 不過,當這些變更複寫和套用至其他對等時,就會偵測衝突。 在點對點複寫中,將變更套用至每個節點的預存程序,會根據每個已發行資料表中的一個或多個隱藏資料行來偵測衝突。

在 SQL Server 2019 (15.x) CU 13 之前,SQL Server 會將一個隱藏的資料行新增至每個已發佈資料表:$sys_p2p_cd_id。 這個隱藏資料行會儲存結合了您針對每個節點指定的 「訂閱者識別碼」 (Originator ID) 與資料列版本的識別碼。

在 SQL Server 2019 (15.x) CU 13 和更新版本上,如果您使用 @p2p_conflictdetection_policy = 'lastwriter' 建立點對點發行集,則 SQL Server 會將額外的隱藏資料行新增至每個已發佈的資料表:$sys_md_cd_id。 這個隱藏的資料行會將日期時間儲存為 datetime2 資料類型。

在同步處理期間,散發代理程式會針對每份資料表執行程序。 這些程序會從其他對等套用插入、更新和刪除作業。 如果其中一項程序在讀取隱藏資料行的值時偵測到衝突,它就會引發嚴重性層級為 16 的錯誤 22815:

A conflict of type '%s' was detected at peer %d between peer %d (incoming), transaction id %s and peer %d (on disk), transaction id %s

根據預設,這項錯誤會導致散發代理程式停止將變更套用至該節點。 如需有關如何處理所偵測衝突的詳細資訊,請參閱處理衝突

注意

隱藏資料行只能由透過「專用管理員連接」(DAC) 登入的使用者存取。 如需 DAC 的資訊,請參閱資料庫管理員的診斷連線

點對點複寫會偵測下列衝突類型:

  • 插入對插入

    參與點對點複寫之每份資料表中的所有資料列都會使用主索引鍵值進行唯一識別。 在多個節點上插入具有相同索引鍵值的資料列時,就會發生插入對插入的衝突。

  • 更新對更新

    在多個節點上更新相同的資料列時發生。

  • 插入對更新

    在某個節點上插入一個資料列,但是在另一個節點上刪除並重新插入相同的資料列時發生。

  • 插入對刪除

    在某個節點上刪除一個資料列,但是在另一個節點上刪除並重新插入相同的資料列時發生。

  • 更新對刪除

    在某個節點上插入一個資料列,但是在另一個節點上刪除相同的資料列時發生。

  • 刪除對刪除

    在多個節點上刪除資料列時發生。

啟用衝突偵測

若要使用衝突偵測,請啟用所有節點的偵測。 根據預設,當您在 SQL Server Management Studio 中設定點對點複寫時,就會啟用衝突偵測。 我們建議您啟用偵測,即使是預期不會發生任何衝突的狀況也一樣。 您可以使用 Management Studio 或 Transact-SQL 預存程序來啟用和停用衝突偵測:

  • 您可以使用 [發行集屬性] 對話方塊的 [訂閱選項] 頁面或「設定點對點拓撲精靈」的 [設定拓撲] 頁面,啟用和停用 Management Studio 中的偵測。

    如果您使用 Management Studio 來設定衝突偵測,散發代理程式就會設定為在偵測到衝突時停止套用變更。

  • 您也可以使用下列預存程序來啟用和停用偵測:

    • sp_addpublication

    • sp_configure_peerconflictdetection.

      如果您使用預存程序來設定衝突偵測,就可以指定散發代理程式是否應該在偵測到衝突時停止套用變更。 代理程式的預設值為停止。 我們建議您使用預設設定。

處理衝突

在點對點複寫中發生衝突時,系統就會引發點對點衝突偵測警示。 設定此警示,以便在發生衝突時收到通知。 如需警示的詳細資訊,請參閱使用複寫代理程式事件的警示

在散發代理程式停止並引發警示之後,請使用下列其中一種方法來處理發生的衝突:

  • 根據包含必要資料的節點備份,重新初始化偵測到衝突的節點 (建議使用的方法)。 這種方法可確保資料處於一致的狀態。

  • 透過讓散發代理程式繼續套用變更,嘗試再次同步處理節點:

    1. 執行 sp_changepublication:針對 @property 參數指定 'p2p_continue_onconflict' 而針對 @value 參數指定 true

    2. 重新啟動散發代理程式。

    3. 使用衝突檢視器來確認偵測到的衝突,然後判斷所涉及的資料列、衝突的類型以及成功者。 系統會根據您在組態設定期間指定的訂閱者識別碼值來解決衝突:源自最高識別碼之節點的資料列會在衝突中獲勝。 如需詳細資訊,請參閱檢視交易式發行集的資料衝突 (SQL Server Management Studio)

    4. 執行驗證,以便確保衝突資料列會正確聚合。 如需詳細資訊,請參閱驗證複寫的資料

      注意

      如果進行這個步驟之後資料出現不一致,您就必須手動更新具有最高優先權之節點上的資料列,然後讓變更從這個節點傳播。 如果拓撲中沒有其他進一步的衝突變更,所有節點都會處於一致狀態。

    5. 執行 sp_changepublication:針對 @property 參數指定 'p2p_continue_onconflict' 而針對 @value 參數指定 false

以最後寫入者勝出來自動處理衝突

從 SQL Server 2019 (15.x) CU 13 開始,您可以在設定點對點複寫時,藉由允許最新的插入或更新來贏得衝突,以此自動解決衝突。 如果任一寫入刪除資料列,SQL Server 則允許該刪除贏得衝突。 此方法稱為最後寫入勝出。

使用預存程序來設定最後寫入勝出。 請參閱設定最後寫入衝突偵測與解決方案。 您無法使用 SQL Server Management Studio 來設定最後寫入勝出。

注意

使用最後寫入者勝出的點對點複寫須取決於參與節點的時鐘同步,如此才能取得可靠的結果。 如果參與伺服器的時鐘不同步,且相差甚遠,則衝突解決的結果可能會不如預期且/或非所需結果。 例如,如果伺服器 A 有準確的時鐘,但伺服器 B 落後一週,則伺服器 A 會贏得每個衝突,即使最後更新資料列的其實不是伺服器 A。 如果無法讓時鐘保持在結果解決方案所需的容錯範圍內,建議您選擇不同的衝突解決方案策略。

另請參閱

@loopback_detection