Replicare colonne Identity

Si applica a:SQL Server e Istanza gestita di SQL di Azure

Quando si assegna una IDENTITY proprietà a una colonna, Microsoft SQL Server genera automaticamente numeri sequenziali per le nuove righe inserite nella tabella contenente la colonna Identity. Per altre informazioni, vedere IDENTITY (Proprietà) (Transact-SQL). Dato che è possibile includere le colonne Identity come parte della chiave primaria, è importante evitare di inserire valori duplicati nelle colonne Identity. Per utilizzare colonne Identity in una topologia di replica con aggiornamenti in più di un nodo, è necessario che ogni nodo presente nella topologia di replica utilizzi un intervallo di valori Identity diverso, in modo da non generare duplicati.

Ad esempio, al Publisher potrebbe essere assegnato l'intervallo 1-100, al Subscriber A l'intervallo 101-200 e al Subscriber B l'intervallo 201-300. Se una riga viene inserita nell'Editore e il valore di identità è, ad esempio, 65, tale valore viene replicato a ogni Sottoscrittore. Quando la replica inserisce i dati in ogni Sottoscrittore, non incrementa il valore della colonna di identità nella tabella del Sottoscrittore; viene invece inserito il valore letterale 65. Il valore della colonna Identity viene incrementato solo in seguito a inserimenti da parte dell'utente e non a inserimenti generati dall'agente di replica.

La replica consente di gestire le colonne Identity di tutti i tipi di pubblicazione e sottoscrizione. È pertanto possibile scegliere di gestire manualmente le colonne oppure di gestirle automaticamente tramite la replica.

Nota

Non è consentito aggiungere una colonna Identity a una tabella pubblicata, perché ciò può impedire la convergenza dei dati durante la replica della colonna nel Sottoscrittore. I valori della colonna Identity nel server di pubblicazione dipendono dall'ordine in cui vengono fisicamente archiviate le righe della tabella interessata. Nel caso in cui le righe siano state archiviate in modo diverso nel Sottoscrittore, il valore della colonna Identity può essere diverso per le stesse righe.

Specificare un'opzione di gestione dell'intervallo Identity

Nella replica sono disponibili tre opzioni di gestione degli intervalli di valori Identity:

  • Automatico. Utilizzata per la replica di tipo merge e la replica transazionale con aggiornamenti nel sottoscrittore. Specificare gli intervalli di dimensioni per l'Editore e i Sottoscrittori e la replica gestisce automaticamente l'assegnazione dei nuovi intervalli. La replica imposta l'opzione NOT FOR REPLICATION sulla colonna identity nel Sottoscrittore, in modo che solo gli inserimenti dell'utente facciano incrementare il valore nel Sottoscrittore.

    Nota

    I sottoscrittori devono sincronizzarsi con il server di pubblicazione per ricevere nuovi intervalli. Dato che gli intervalli di valori Identity vengono assegnati automaticamente ai Sottoscrittori, è possibile che un Sottoscrittore esaurisca gli intervalli disponibili se ne richiede ripetutamente di nuovi.

  • Manuale. Utilizzato per la replica snapshot e transazionale senza aggiornamenti nel Sottoscrittore, per la replica transazionale peer-to-peer oppure se l'applicazione deve controllare gli intervalli Identity a livello di programmazione. Se si sceglie la gestione manuale, è necessario verificare che gli intervalli vengano assegnati al server di pubblicazione e a tutti i Sottoscrittori e che vengano assegnati nuovi intervalli se quelli iniziali sono già in uso. Nella replica l'opzione NOT FOR REPLICATION viene impostata nella colonna Identity del Sottoscrittore.

  • Nessuno. Questa opzione è consigliata solo per la retrocompatibilità con le versioni precedenti di SQL Server ed è disponibile solo tramite l'interfaccia della stored procedure per le pubblicazioni transazionali.

Per specificare un'opzione di gestione degli intervalli di valori Identity, vedere Gestire le colonne Identity.

Assegnazione degli intervalli di valori Identity

In questa sezione vengono descritti i diversi metodi di assegnazione degli intervalli utilizzati per la replica di tipo merge e per la replica transazionale.

Quando si replicano colonne Identity, occorre tenere conto di due tipi di intervalli: gli intervalli assegnati al Publisher e ai Subscriber e l'intervallo del tipo di dati della colonna. Nella tabella seguente vengono illustrati gli intervalli disponibili per i tipi di dati utilizzati in genere nelle colonne Identity. L'intervallo è applicato a tutti i nodi presenti in una topologia. Ad esempio, se si utilizza smallint con un valore iniziale di 1 e con un incremento di 1, il numero massimo di inserimenti possibili è 32.767 per il server di pubblicazione e tutti i Sottoscrittori. Il numero effettivo di inserimenti dipende dal fatto che vi siano o meno gap nei valori utilizzati e che venga utilizzato o meno un valore soglia. Per ulteriori informazioni sulle soglie, vedere le sezioni seguenti relative alla replica di merge e alla replica transazionale con sottoscrizioni ad aggiornamento in coda.

Se l'Editore esaurisce il proprio intervallo di valori IDENTITY dopo un inserimento, può assegnare automaticamente un nuovo intervallo se l'inserimento è stato eseguito da un membro del ruolo predefinito del database db_owner. Se l'inserimento è stato eseguito da un utente che non appartiene a tale ruolo, Log Reader Agent, agente di merge oppure un utente membro del ruolo db_owner deve eseguire sp_adjustpublisheridentityrange (Transact-SQL). Nel caso di pubblicazioni transazionali, l'agente di lettura log deve essere in esecuzione per allocare automaticamente un nuovo intervallo di valori (per impostazione predefinita l'agente viene eseguito continuamente).

Avviso

Durante un inserimento batch di grandi dimensioni, il trigger di replica viene attivato solo una volta, non per ogni riga dell'inserimento. Ciò può causare un errore dell'istruzione insert se un intervallo identity viene esaurito durante un inserimento di grandi dimensioni, ad esempio un'istruzione INSERT INTO .

Tipo di dati Intervallo
tinyint Non supportato per la gestione automatica
smallint da -2^15 (-32.768) a 2^15-1 (32.767)
int da -2^31 (-2.147.483.648) a 2^31-1 (2.147.483.647)
bigint da -2^63 (-9.223.372.036.854.775.808) a 2^63-1 (9.223.372.036.854.775.807)
decimal e numeric da -10^38+1 a 10^38-1

Nota

Per creare un numero a incremento automatico da usare in più tabelle o da chiamare dalle applicazioni senza fare riferimento ad alcuna tabella, vedere Numeri di sequenza.

Replica di tipo merge

Gli intervalli di valori identity sono gestiti dal Publisher e propagati ai Subscriber dal agente di merge (in una gerarchia di ripubblicazione, gli intervalli sono gestiti dal Publisher radice e dai server di ripubblicazione). I valori di identità vengono assegnati da un pool nel server di pubblicazione. Quando si aggiunge un articolo con una colonna di tipo identity a una pubblicazione nella Creazione guidata Nuova pubblicazione o utilizzando sp_addmergearticle (Transact-SQL), è necessario specificare i valori seguenti:

  • Il parametro @identity_range, che controlla la dimensione dell'intervallo di valori Identity inizialmente allocato sia all'Editore sia ai sottoscrittori con sottoscrizioni client.

    Nota

    Per i Sottoscrittori che eseguono le precedenti versioni di SQL Server, questo parametro, e non il parametro @pub_identity_range, controlla anche le dimensioni dell'intervallo di valori Identity nei Sottoscrittori di ripubblicazione.

  • Il parametro @pub_identity_range, che controlla la dimensione dell'intervallo di identità allocato ai sottoscrittori con sottoscrizioni al server per la ripubblicazione (necessario per la ripubblicazione dei dati). Tutti i Sottoscrittori con sottoscrizioni server ricevono un intervallo per la ripubblicazione, anche se non eseguono la ripubblicazione dei dati.

  • Il parametro @threshold, usato per determinare quando è necessario un nuovo intervallo di valori Identity per una sottoscrizione di SQL Server Compact o una versione precedente di SQL Server.

Ad esempio, è possibile specificare 10000 per @identity_range e 500000 per @pub_identity_range. Al server di pubblicazione e a tutti i Sottoscrittori che eseguono SQL Server 2005 (9.x) o versione successiva, incluso il Sottoscrittore con la sottoscrizione server, viene assegnato un intervallo primario di 10000. Al Sottoscrittore con la sottoscrizione server viene inoltre assegnato un intervallo primario di 500000, che può essere usato dai Sottoscrittori che eseguono la sincronizzazione con il Sottoscrittore di ripubblicazione. È inoltre necessario specificare i parametri @identity_range, @pub_identity_range e @threshold per gli articoli della pubblicazione nel Sottoscrittore di ripubblicazione.

Tutti i Sottoscrittori che eseguono SQL Server 2005 (9.x) o versione successiva ricevono inoltre un intervallo di valori Identity secondario. Questo valore secondario ha le stesse dimensioni dell'intervallo primario. Quando quest'ultimo si esaurisce viene utilizzato l'intervallo secondario. L'agente di merge assegna al Sottoscrittore un nuovo intervallo, Il nuovo intervallo diventa l'intervallo secondario e il processo continua man mano che il Sottoscrittore utilizza i valori di identità.

Replica transazionale con sottoscrizioni di aggiornamento in coda

Gli intervalli di valori Identity vengono gestiti dal server di distribuzione e distribuiti ai Sottoscrittori dall'agente di distribuzione. I valori Identity vengono assegnati da un pool nel server di distribuzione. Le dimensioni del pool dipendono dalle dimensioni del tipo di dati e dall'incremento utilizzato per la colonna Identity. Quando si aggiunge un articolo con una colonna IDENTITY a una pubblicazione nella procedura guidata Nuova pubblicazione o usando la stored procedure sp_addarticle (Transact-SQL), si specificano i valori per:

  • Il parametro @identity_range, che controlla la dimensione dell'intervallo di identità inizialmente allocato a tutti i sottoscrittori.

  • Il parametro @pub_identity_range, che controlla la dimensione dell'intervallo di identità allocato al Publisher.

  • Il parametro @threshold, utilizzato per determinare quando è necessario un nuovo intervallo di identità per una sottoscrizione.

Ad esempio, è possibile specificare 10000 per @pub_identity_range, 1000 per @identity_range (presupponendo aggiornamenti minori nel Sottoscrittore) e 80% per @threshold. Dopo 800 inserimenti in un Sottoscrittore, pari all'80% di 1000, al Sottoscrittore viene assegnato un nuovo intervallo. Dopo 8.000 inserimenti nel server di pubblicazione, al server di pubblicazione viene assegnato un nuovo intervallo. Quando viene assegnato un nuovo intervallo, nei valori dell'intervallo di identità della tabella si verificherà un'interruzione. Specificando una soglia più elevata si avranno gap più piccoli, ma il sistema sarà meno tollerante agli errori. Se per qualche ragione non è possibile eseguire l'agente di distribuzione, i Sottoscrittori potrebbero esaurire più facilmente i valori Identity.

Assegnazione di intervalli per la gestione manuale degli intervalli di valori Identity

Se si specifica la gestione manuale degli intervalli di identità, è necessario assicurarsi che il Publisher e ogni Subscriber utilizzino intervalli di identità diversi. Si consideri, ad esempio, una tabella nel server di pubblicazione con una colonna Identity definita come IDENTITY(1,1): la colonna Identity comincia col valore 1 e viene incrementata di 1 ogni volta che viene inserita una riga. Se la tabella nel Pubblicatore contiene 5.000 righe e si prevede che il numero di righe aumenti nel corso del ciclo di vita dell'applicazione, il Pubblicatore potrebbe utilizzare l'intervallo 1-10.000. Nel caso vi siano due Sottoscrittori, per il Sottoscrittore A si potrebbe usare l'intervallo 10.001-20.000 e per il Sottoscrittore B l'intervallo 20.001-30.000.

Dopo che un sottoscrittore è stato inizializzato con uno snapshot o con un altro mezzo, eseguire DBCC CHECKIDENT per assegnare al sottoscrittore un valore iniziale per il relativo intervallo di valori identity. Ad esempio, nel Sottoscrittore A si eseguirà DBCC CHECKIDENT('<TableName>','reseed',10001), Nel Sottoscrittore B, eseguiresti CHECKIDENT('<TableName>','reseed',20001).

Per assegnare nuovi intervalli al Server di pubblicazione o ai Sottoscrittori, eseguire DBCC CHECKIDENT, specificando un nuovo valore per reimpostare il valore iniziale della tabella. È consigliabile definire un metodo per determinare quando è necessario assegnare un nuovo intervallo. Ad esempio, nell'applicazione potrebbe esserci un meccanismo che rileva quando un nodo sta per esaurire il proprio intervallo e quindi consente di assegnare un nuovo intervallo mediante DBCC CHECKIDENT. È inoltre possibile aggiungere un vincolo CHECK per impedire che venga aggiunta una riga se ciò determina l'utilizzo di un valore Identity non compreso nell'intervallo disponibile.

Gestione degli intervalli Identity dopo il ripristino di un database

Se si utilizza la gestione automatica dell'intervallo di valori identity, quando un Sottoscrittore viene ripristinato da un file di backup, richiede automaticamente un nuovo intervallo di valori identity. Se un server di pubblicazione viene ripristinato da un backup, è necessario verificare che al server di pubblicazione venga assegnato l'intervallo appropriato. Per la replica di tipo merge, assegnare un nuovo intervallo mediante sp_restoremergeidentityrange (Transact-SQL). Nella replica transazionale determinare il valore massimo utilizzato e quindi impostare il punto di partenza dei nuovi intervalli. Utilizzare la procedura seguente dopo aver ripristinato il database di pubblicazione:

  1. Interrompere ogni attività di tutti i sottoscrittori.

  2. Per ogni tabella pubblicata che include una colonna di identità:

    1. Nel database di sottoscrizione di ogni Sottoscrittore eseguire IDENT_CURRENT('<TableName>').

    2. Registrare il valore massimo rilevato in tutti i Sottoscrittori.

    3. Nel database delle pubblicazioni nel Publisher, eseguire DBCC CHECKIDENT(<TableName>','reseed',<HighestValueFound+1>).

    4. Nel database delle pubblicazioni del Publisher, eseguire sp_adjustpublisheridentityrange <PublicationName>, <TableName>.

    Nota

    Se il valore nella colonna Identity viene impostato per essere decrementato anziché incrementato, registrare il valore minimo rilevato e quindi reinizializzare tale valore.