複寫識別欄位
將 IDENTITY 屬性指派給資料行時,MicrosoftSQL Server 會自動為含有識別欄位之資料表的新資料列產生序號。如需詳細資訊,請參閱<IDENTITY (屬性) (Transact-SQL)>。由於識別欄位可能會做為主索引鍵的一部分,因此請務必避免在識別欄位中重複值。若要在具有多個節點更新的複寫拓撲裡使用識別欄位,複寫拓撲中的每個節點必須使用不同的識別值範圍,以免出現重複。
例如,可為「發行者」指派範圍 1-100,為「訂閱者 A」指派範圍 101-200,為「訂閱者 B」指派範圍 201-300。如果資料行在「發行者」端插入且識別值是 65,則該值會複寫至每個「訂閱者」。當複寫在每個「訂閱者」端插入資料時,不會遞增「訂閱者」資料表中的識別欄位值,而是插入常值 65。只有使用者插入會導致識別欄位值遞增,複寫代理程式插入則不會。
複寫會處理所有發行集與訂閱類型的識別欄位,讓您能夠手動管理資料行,或者讓複寫自動管理這些資料行。
[!附註]
不支援在已發行的資料表上加入識別欄位,因為可能在資料行複寫至「訂閱者」時,導致無法聚合。發行者端識別欄位中的值,隨著受影響的資料表之資料列的實際儲存順序而不同。資料列可能以不同方式儲存在訂閱者端;因此識別欄位的值可能與同資料列的不同。
指定識別範圍管理選項
複寫提供三個識別範圍管理選項:
自動。用於「訂閱者」端更新的合併式複寫與交易式複寫。指定「發行者」與「訂閱者」的大小範圍,複寫會自動管理新範圍的指派。複寫還會為「訂閱者」端的識別欄位設定 NOT FOR REPLICATION 選項,以便只有使用者插入會導致值在「訂閱者」端遞增。如需詳細資訊,請參閱<使用 NOT FOR REPLICATION 控制條件約束、識別和觸發程序>。
[!附註]
「訂閱者」必須與「發行者」同步,方可接收新範圍。由於「訂閱者」的識別範圍是自動指派的,因此如果反覆要求新範圍,任何「訂閱者」都可能用盡整個識別範圍。
手動。用於「訂閱者」端沒有更新的快照式與交易式複寫、點對點交易式複寫,或者是應用程式必須程式化控制識別範圍的情況。如果指定手動管理,必須確定範圍指派到了「發行者」與每個「訂閱者」,並在使用初始範圍時指派新範圍。複寫會為「訂閱者」端的識別欄位設定 NOT FOR REPLICATION 選項。
無。此選項僅建議用於與舊版 SQL Server 的回溯相容性,並且僅在交易式發行集的預存程序介面可用。
若要指定識別範圍管理選項
SQL Server Management Studio: 如何:管理識別欄位 (SQL Server Management Studio)
複寫 Transact-SQL 程式設計:如何:管理識別欄位 (複寫 Transact-SQL 程式設計)
指派識別範圍
合併式複寫與交易式複寫使用不同的方法指派範圍;這些方法在本節中均有描述。
複寫識別欄位時要考慮兩種範圍:指派至「發行者」與「訂閱者」的範圍,以及資料行中資料類型的範圍。下表顯示識別欄位中通常使用之資料類型可用的範圍。範圍用於拓撲中的所有節點。例如,如果您使用 smallint 從 1 開始,遞增值為 1,則最多可為「發行者」與所有「訂閱者」插入 32,767 次。插入的實際數目取決於使用的值中是否有間距,以及是否使用臨界值。如需臨界值的詳細資訊,請參閱下列的「合併式複寫」和「具有佇列更新訂閱的交易式複寫」各節。
如果「發行者」在插入之後用盡了其識別範圍,則在 db_owner 固定資料庫角色的成員執行插入時,可自動指派新範圍。如果執行插入的使用者並非該角色,則「記錄讀取器代理程式」、「合併代理程式」或屬於 db_owner 角色成員的使用者必須執行 sp_adjustpublisheridentityrange (Transact-SQL)。對於交易式複寫,「記錄讀取器代理程式」必須執行才能自動配置新範圍 (預設要求該代理程式連續執行)。
資料類型 |
範圍 |
---|---|
tinyint |
不支援自動管理 |
smallint |
-2^15 (-32,768) 到 2^15-1 (32,767) |
int |
-2^31 (-2,147,483,648) 到 2^31-1 (2,147,483,647) |
bigint |
-2^63 (-9,223,372,036,854,775,808) 到 2^63-1 (9,223,372,036,854,775,807) |
decimal 及numeric |
-10^38+1 到 10^38-1 |
合併式複寫
識別範圍由「發行者」管理,並由「合併代理程式」傳播至「訂閱者」(在重新發行階層中,範圍由根「發行者」與重新發行者管理)。識別值從「發行者」端的集區指派。您在新增發行集精靈中或使用 sp_addmergearticle (Transact-SQL) 將具有識別欄位的發行項加入發行集時,指定下列的值:
@identity_range 參數,控制最初配置給「發行者」以及具有主訂閱之「訂閱者」的識別範圍大小。
[!附註]
對於執行舊版 SQL Server 的「訂閱者」,此參數 (而非 @pub_identity_range 參數) 還控制重新發行「訂閱者」端的識別範圍大小。
@pub_identity_range 參數,控制配置給「訂閱者」(具有主訂閱,為重新發行資料所需要) 之重新發行的識別範圍大小。所有具有主訂閱的「訂閱者」都會收到重新發行的範圍,即使它們實際並未重新發行資料。
@threshold 參數,用於確定 SQL Server Compact 3.5 SP1 或舊版 SQL Server 的訂閱何時需要新的識別範圍。
例如,您可以為 @identity_range 指定 10000,為 @pub_identity_range 指定 500000。執行 SQL Server 2005 或更新版本的發行者和所有訂閱者 (包括具有主訂閱的訂閱者) 都會被指派 10000 的主要範圍。具有主訂閱的訂閱者也會被指派 500000 的主要範圍,這可供與重新發行訂閱者同步的訂閱者使用 (您還必須為重新發行訂閱者端之發行集中的發行項指定 @identity_range、@pub_identity_range 與 @threshold)。
執行 SQL Server 2005 或更新版本的每一個訂閱者還會收到次要識別範圍。次要範圍的大小等於主要範圍;當主要範圍用盡時,就會使用次要範圍,並且「合併代理程式」會為「訂閱者」指派新的範圍。新範圍隨即成為次要範圍,且當「訂閱者」使用識別值時處理會繼續。
執行 SQL Server Compact 3.5 SP1 或舊版 SQL Server 的「訂閱者」僅會指派到主要範圍;新範圍的指派由 @threshold 參數控制。此外,重新發行「訂閱者」僅具有 @identity_range 參數中指定的範圍;它必須將此範圍用於本機變更以及與重新發行「訂閱者」同步的「訂閱者」端變更。例如,您可以為 @pub_identity_range 指定 10000,為 @identity_range 指定 500000,為 @threshold 指定 80%。在「訂閱者」端執行 8000 次 (10000 的 80%) 插入之後,將為「發行者」指派新範圍。指派新範圍時,資料表裡的識別範圍值中會有一個間隔。指定的臨界值越高間距就越小,但系統的容錯功能也就越弱:如果「合併代理程式」因某種原因無法執行,「訂閱者」可能更容易用盡識別。
具有佇列更新訂閱的交易式複寫
識別範圍由「散發者」管理,並由「散發代理程式」傳播至「訂閱者」。識別值從「散發者」端的集區指派。集區大小基於資料類型的大小以及用於識別欄位的遞增值。您在新增發行集精靈中或使用 sp_addarticle (Transact-SQL) 將具有識別欄位的發行項加入發行集時,指定下列的值:
@identity_range 參數,控制最初配置給所有「訂閱者」的識別範圍大小。
@pub_identity_range 參數,控制配置給「發行者」的識別範圍大小。
@threshold 參數,用於確定訂閱何時需要新的識別範圍。
例如,您可以為 @pub_identity_range 指定 10000,為 @identity_range 指定 1000 (假設在「訂閱者」端沒有什麼更新),為 @threshold 指定 80%。在「訂閱者」端執行 800 次插入 (1000 的 80%) 之後,將為「訂閱者」指派新範圍。在「發行者」端執行 8000 次插入之後,將為「發行者」指派新範圍。指派新範圍時,資料表裡的識別範圍值中會有一個間隔。指定的臨界值越高間距就越小,但系統的容錯功能也就越弱:如果「散發代理程式」因某種原因無法執行,「訂閱者」可能更容易用盡識別。
為手動識別範圍管理指派範圍
如果指定手動識別範圍管理,則必須確定「發行者」與每個「訂閱者」都使用不同的識別範圍。例如,考慮識別欄位定義為 IDENTITY(1,1) 之「發行者」端的資料表:識別欄位從 1 開始,每插一個資料列即遞增 1。如果「發行者」端的資料表有 5,000 個資料列,而您希望在應用程式使用期間資料表有所成長,「發行者」可以使用範圍 1-10,000。假設有兩個「訂閱者」,「訂閱者 A」可以使用 10,001–20,000,「訂閱者 B」可以使用 20,001-30,000。
在「訂閱者」透過快照集或其他方式初始化之後,執行 DBCC CHECKIDENT 以為「訂閱者」指派識別範圍的起點。例如,在「訂閱者 A」端,應執行 DBCC CHECKIDENT('<TableName>','reseed',10001)。在「訂閱者 B」端,應執行 CHECKIDENT('<TableName>','reseed',20001)。
若要指派新範圍至「發行者」或「訂閱者」,請執行 DBCC CHECKIDENT 並指定新值以重設資料表的種子資料。您應該採用某種方式來確定必須在何時指派新範圍。例如,您的應用程式可能有一個機制,可以偵測節點將用盡其範圍的時間,並使用 DBCC CHECKIDENT 指派新範圍。您也可以新增檢查條件約束,以確保在可能超出識別值使用範圍的情況下無法再新增資料列。
在資料庫還原後處理識別範圍
如果使用自動識別範圍管理,則「訂閱者」從備份還原時,會自動要求新的識別範圍值。如果「發行者」從備份還原,您必須確定為該「發行者」指派了適當的範圍。對於合併式複寫,請使用 sp_restoremergeidentityrange (Transact-SQL) 指派新的範圍。對於交易式複寫,先確定已使用的最大值,然後設定新範圍的起點。在發行集資料庫還原後使用下列程序:
停止所有「訂閱者」上的所有活動。
對於每個包括識別欄位的已發行資料表:
在每個「訂閱者」端的訂閱資料庫中,執行 IDENT_CURRENT('<TableName>')。
記錄所有「訂閱者」中找到的最大值。
在「發行者」端的發行集資料庫中,執行 DBCC CHECKIDENT(<TableName>','reseed',<HighestValueFound+1>)。
在「發行者」端的發行集資料庫中,執行 sp_adjustpublisheridentityrange <PublicationName>, <TableName>。
[!附註]
如果識別欄位中的值設定為遞減而非遞增,請記錄找到的最小值,然後用該值重設種子資料。