SQL Server 在不同的產生批次處理子級和父系代時的非收斂

本文可協助您解決 SQL Server 在個別的產生批次中處理子系及父系代時發生的非收斂問題。

原始產品版本:   Sqlserver
原始 KB 編號:   308266

徵狀

在下列情況下,訂閱者的子表中的插入指令遺失可能會發生:

  • 合併複寫拓撲是階層式,具有發行者、一或多個 republishers,以及一或多個訂閱者。
  • 一個或多個父項和子項文章會存在於合併複寫出版物中,並在兩者之間定義聯接篩選。
  • 在重新 NOT FOR REPLICATION 發行者和訂閱者上,存在這兩篇文章間關聯的外鍵約束。
  • 插入子專案時,會從其相關聯的父代產生與 merge agent 參數中指定的值不同的代產生 -DownloadGenerationsPerBatch 。 因此,合併代理程式會在一批代中處理子項產生,與其相關聯的上級產生區分開。
  • 發行者與重新發佈程式之間的合併處理會中斷,而且在處理子和父系產生批次之間。

因應措施

合併複寫架構不會提供一種機制,可將父項和子項變更與產生的批次邊界保持在一起。 若要解決此問題,您可以執行下列其中一項動作:

  • -UploadGenerationsPerBatch -DownloadGenerationsPerBatch 代理程式參數的最大值增加至最大值2000,這可讓您在批次中的產生過程中,處理子文章的產生,以與父篇文章的產生分開處理的可能性。

-或-

  • 在重新 NOT FOR REPLICATION 發行者的外鍵限制中移除此屬性。 在此情況下,合併代理程式無法將列插入子專案中,因為沒有相關聯的父專案列。 不過,請記住,此變更可能會產生效能降級。 如果合併代理程式無法插入這些子列,必須 重試 這些變更。 合併代理程式重試程式的效率不如其正常的批次處理模式。

詳細資訊

以下是可能發生此問題的詳細事件順序。 -UploadGenerationsPerBatch-DownloadGenerationsPerBatch 合併代理程式參數的預設值 (在此問題大的) 為100。 在下列範例中,假設 -UploadGenerationsPerBatch and 參數尚未 -DownloadGenerationsPerBatch 變更。

  • 會在最上層的 publisher 上插入子系及父篇文章。 子專案是指出版物中的任何專案,具有對另一個表格的外鍵約束,稱為父篇文章。 這兩篇文章是由合併複寫聯接篩選器所關聯,且重新發行者和訂閱者的實際伺服器端外鍵限制都是以 NOT FOR REPLICATION 屬性標示。 您可以在資料表上執行 sp_help 的預存程式,以判斷限制是否不用於複寫,如果您不確定。
  • 插入子表中的插入子表會產生 (例如,代110的) 。 在父表中插入會發生 (例如,代250的) 。 這兩個代間的分隔大於 -DownloadGenerationsPerBatch 參數。
  • 發行者-重新發佈程式合併代理程式會處理包含101到200的代批次。 成功處理此批次,並將這些代數中相關聯的變更下載至重新發佈伺服器後,發行者重新發佈器合併代理程式會中斷。 當合併代理程式可以處理代201至 300 (包含) 的父專案變更時,就會發生中斷。 中斷可能是因為網路連線中斷、查詢超時等等。 合併代理程式可以認可不含父列的子專案列,因為伺服器端外鍵約束已標示為 NOT 進行複寫,因此會 "擱置" 該限制的檢查。
  • 在重新發佈發行者的合併代理程式重新開始處理之前,重新發行者的合併代理程式會開始進行合併會話。 它會開始從重新發行者下載變更的處理常式。
  • 當重新發行者的合併代理程式處理產生110時 (子專案會插入) ,它會評估子專案與父專案之間的 join 篩選器的出現。 因為父專案變更尚未抵達重新發行者,所以合併代理程式會判斷這些子插入不會「限定」 join 篩選。 合併代理程式會下載代表代110的 MSmerge_genhistory 列,但該產生中沒有任何變更。 此合併代理程式成功完成其會話。
  • 在發行者與重新發佈程式間,後續執行的合併代理程式會順利處理包含父專案的代批次, (代數201至 300) 並在重新發佈伺服器提交這些變更。
  • 最後,在重新發行者與訂閱者之間,後續的合併代理程式會話會考慮產生250,並將父-文章插入下載至訂閱者。 不過,因為訂閱者也知道產生 110 (子項文章的產生) ,所以合併代理程式不會重新評估子文章的分割區。

這會導致在重新發行者上,具有子資料列的正確父篇文章列出現 orphaned