共用方式為


合併式複寫如何追蹤和列舉變更

初始化發行集或訂用帳戶之後,合併式複寫會追蹤並列舉已發佈資料表中資料的所有變更。 變更是透過觸發器(複寫會為每個已發佈的資料表建立的)以及發行集和訂閱資料庫中的系統資料表來追蹤。 這些複寫系統表格包含中繼資料,標示應該傳播哪些變更。 當合併代理程式在同步處理期間執行時,代理程式會列舉變更,然後視需要套用至發行者和訂閱者。

變更追蹤

合併式複寫會使用下列觸發程式和系統資料表來追蹤所有已發佈資料表的變更:

  • MSmerge_ins_<GUID>:插入觸發程序 (此觸發程序和其他觸發程序的 GUID 值衍生自 sysmergearticles
  • MSmerge_upd_<GUID>:更新觸發器
  • MSmerge_del_<GUID>:刪除觸發器
  • MSmerge_contents
  • MSmerge_tombstone
  • MSmerge_genhistory

合併式複寫會使用下列額外的系統資料表來追蹤篩選資料表的變更:

  • MSmerge_partition_groups
  • MSmerge_current_partition_mappings
  • MSmerge_past_partition_mappings

備註

列出的系統表格會由資料庫中的所有合併發行項目及訂閱項目使用; 例如,如果您在發行集資料庫中有多個發行項目,MSmerge_contents 則包含所有發行項目中文章的資料列。

未篩選資料表的變更追蹤

系統數據表

用於未篩選和篩選資料表的系統資料表中包含以下中繼資料:

  • MSmerge_contents 包含資料庫中已發佈表格中插入或更新的每一列的一列。

  • MSmerge_tombstone 包含從資料庫中已發佈表格中刪除的每一列的一列。

  • MSmerge_genhistory 包含每一代的一列。 世代是傳遞至發行者或訂閱者的變更集合。 每次執行合併代理程式時,都會 關閉 世代;資料庫中的後續變更會新增至一或多個 開啟世代

變更追蹤程式

下列變更追蹤程式會用於所有未篩選的資料表:

  • 當已發佈表格上發生插入或更新時,觸發MSmerge_ins_<GUID>MSmerge_upd_<GUID>觸發程式,並將一列插入MSmerge_contents系統表格中。 這個rowguid欄位在MSmerge_contents欄中包含了插入或更新資料列的 GUID,指出下次同步處理發生時,使用者資料表中對應的插入或更新資料列應該傳送給發行者或訂閱者。 如果使用者資料表中的資料列發生後續更新,則會更新 中的 MSmerge_contents 資料列以反映此狀態。

  • 當已發佈的資料表上發生刪除時,MSmerge_del_<GUID> 觸發程式會觸發,並將一個資料列插入 MSmerge_tombstone 系統資料表中。 rowguidMSmerge_tombstone欄包含已刪除資料列的 GUID,表示下次發生同步處理時,刪除操作應傳送至在使用者資料表中對應已刪除資料列的發行者或訂閱者。 如果已刪除的列在MSmerge_contents中有參照(因為自上次同步處理以來已插入或更新),則會從MSmerge_contents中刪除。

已篩選資料表的變更追蹤

系統數據表

除了上一節所述的系統資料表之外,發行集資料庫中的三個資料表還包含中繼資料,用於追蹤已篩選資料表的變更:

  • MSmerge_partition_groups 包含發佈中定義的每一個分割區的一列。 分割區可以是:

    • 透過sp_addmergepartition或[發佈內容] 對話方塊的 [資料分割區] 頁面明確定義。

    • 如果訂閱者需要分割區,而分割區尚未具有 MSmerge_partition_groups中 的項目,則會在訂閱者同步時自動建立。

  • MSmerge_current_partition_mappings包含來自MSmerge_contentsMSmerge_partition_groups的每個唯一列組合的一行。 例如,如果使用者表格中的一列屬於兩個分割區,且該列已更新,則會插入 MSmerge_contents 一列以反映更新,並將兩列插入 MSmerge_current_partition_mappings,以指出更新的列屬於兩個分割區。

  • MSmerge_past_partition_mappings 包含不再屬於指定分割區的每一列的一列。 在下列情況下,列會移出分割區:

    • 列已刪除。 如果從使用者表格中刪除列,則會將列插入到 MSmerge_tombstone 中,並將一或多列插入 MSmerge_past_partition_mappings中。

    • 用於篩選的資料行中的值已變更。 例如,如果參數化篩選是以公司總部所在的州為基礎,且公司移動,則公司的資料列 (以及其他資料表中的相關資料列) 可能會從一個銷售人員的資料分割區移至另一個銷售人員的資料分割區。 如果更新了列,使其不再屬於分割區,則會在 中 MSmerge_contents 插入或更新一列,並將一或多個列插入 MSmerge_past_partition_mappings中。

備註

如果使用非重疊分割區,每個分割區只有一個訂用者(3@partition_options參數的sp_addmergearticle值),則系統資料表MSmerge_current_partition_mappingsMSmerge_past_partition_mappings不會用來追蹤資料列的分割區映射,因為每個資料列僅屬於一個分割區,且只能在一個訂閱者上變更。

變更追蹤程式

在先前所述的程序 (在 未篩選資料表的變更追蹤一節中)中,這個程序同樣適用於篩選的資料表,並增加了以下幾個步驟:

  • 當在已發佈的表格上進行插入操作時,除了更新或插入 MSmerge_contents 資料之外,還會針對每個該列所屬的分割區,在 MSmerge_current_partition_mappings 中新增一個分割區映射。

  • 當已發佈的資料表發生更新時,除了更新或插入 MSmerge_contents資料之外,如果資料列所屬的每個分割區不存在 MSmerge_current_partition_mappings 分割區對應,則會新增一個分割區對應。 如果更新導致將列從一個分割區移至另一個分割區,則會在 中 MSmerge_current_partition_mappings 更新一列,並將一列新增至 MSmerge_past_partition_mappings

  • 當刪除操作發生在已發佈的表格時,除了將一列插入MSmerge_tombstone之外,還會從MSmerge_current_partition_mappings中刪除一列,並將一列新增至MSmerge_past_partition_mappings

變更列舉

系統表格和程序

當合併代理程式執行時,會使用數個系統資料表和預存程序列舉變更:

  • MSmerge_genhistory 包含每一代的一列。 世代是傳遞至發行者或訂閱者的變更集合。 每次執行合併代理程式時,都會 關閉 世代;資料庫中的後續變更會新增至一或多個 開啟世代

  • sysmergesubscriptions 包含訂閱的相關資訊,包括節點傳送及接收的最後幾代變更記錄。 在發行集資料庫中,此資料表包含發行者的資料列,以及每個訂閱者的一資料列。 在訂閱資料庫中,此資料表通常包含訂閱者的資料列和發行者的資料列。

  • MSmerge_generation_partition_mappings 僅用於過濾的資料表,記錄給定的世代是否包含與給定分割區相關的任何變更。 此發行資料庫中的表格包含來自MSmerge_genhistoryMSmerge_partition_groups的每一個唯一列組合的一行。

  • sp_MSmakegeneration 在列舉程序開始時關閉所有開啟的世代。

  • sp_MSenumchanges 列舉資料表的變更 (此程序也會使用名稱開頭的 sp_MSenumchanges 數個相關程序)。

  • sp_MSgetmetadata 決定是否應將一個節點的變更套用至另一個節點,做為插入、更新或刪除。

變更列舉程序

在變更列舉期間會發生下列程序:

  1. 系統程序 sp_MSmakegeneration 稱為:

    • 對於未過濾和過濾的表格,此程序會關閉所有在MSmerge_genhistory中引用的開啟世代(在欄位genstatus中封閉的世代具有12的值)。

    • 對於篩選過的表格,此程序會將資料填入系統表格 MSmerge_generation_partition_mappings。 如果世代包含與分割區相關的一或多個變更,則會將列插入系統表格中。 如果某個世代不包含與指定分割區相關的任何變更,則不會將資料列插入 MSmerge_generation_partition_mappings,也不會為接收該分割區的任何訂閱者列舉變更。

  2. 呼叫預存程序 sp_MSenumchanges 和相關程序。 下列程序會列舉自上次同步處理發生以來所發生的變更:

    1. 這些程序首先根據表格sysmergesubscriptions中的直欄 sentgen (最後傳送的世代) 和 recgen (收到的最後世代) 來決定列舉開始的世代。

      例如,當判斷必須列舉指定訂閱者的哪些世代變更時,會比較訂閱者的 ( sentgen 儲存在發行集資料庫中) 和訂閱者的 ( recgen 儲存在訂閱資料庫中)。 如果值相同 (表示訂閱者已成功收到從發行者傳送的上一代) ,則會從 中的 MSmerge_genhistory下一代開始列舉變更。 如果值不相同,則會使用兩個值中較低的值來確保傳送所有必要的變更。

    2. 然後,程序會列舉變更:

      對於未篩選的資料表,所有在sentgenrecgen中的世代之後的變更都會被列舉:MSmerge_genhistory會與MSmerge_contentsMSmerge_tombstone組合,以決定必須傳送哪些變更。

      對於篩選的資料表, MSmerge_generation_partition_mappings 會聯結至: MSmerge_current_partition_mappingsMSmerge_contents;和 MSmerge_past_partition_mappings 和 , MSmerge_tombstone 以判斷哪些變更與訂閱者收到的分割區相關。

  3. 呼叫預存程式 sp_MSgetmetadata 來判斷變更是否應該套用為插入、更新或刪除。 此時,執行衝突偵測和解決;如需詳細資訊,請參閱 合併式複寫如何偵測和解決衝突