Utilizzare il rilevamento delle modifiche (SQL Server)Work with Change Tracking (SQL Server)

QUESTO ARGOMENTO SI APPLICA A:sìSQL Server (a partire dalla versione 2008)sìDatabase SQL di AzurenoAzure SQL Data Warehouse noParallel Data Warehouse THIS TOPIC APPLIES TO:yesSQL Server (starting with 2008)yesAzure SQL DatabasenoAzure SQL Data Warehouse noParallel Data Warehouse

Le applicazioni che utilizzano il rilevamento delle modifiche devono essere in grado di ottenere le modifiche registrate, di applicare tali modifiche a un altro archivio dati e di aggiornare il database di origine.Applications that use change tracking must be able to obtain tracked changes, apply these changes to another data store, and update the source database. In questo argomento viene descritto come eseguire queste attività e viene illustrato il ruolo svolto dal rilevamento delle modifiche quando si verifica un failover ed è necessario ripristinare un database da un backup.This topic describes how to perform these tasks, and also the role change tracking plays when a failover occurs and a database must be restored from a backup.

Utilizzo delle funzioni di rilevamento delle modifiche per ottenere le modifiche Obtain Changes by Using Change Tracking Functions

Viene descritto come utilizzare le funzioni di rilevamento delle modifiche per ottenere le modifiche apportate al database e le informazioni relative.Describes how to use the change tracking functions to obtain changes and information about the changes that were made to a database.

Informazioni sulle funzioni di rilevamento delle modificheAbout the Change Tracking Functions

Per ottenere le modifiche apportate a un database e le relative informazioni, nelle applicazioni è possibile utilizzare le funzioni seguenti:Applications can use the following functions to obtain the changes that are made in a database and information about the changes:

CHANGETABLE(CHANGES …)CHANGETABLE(CHANGES …) function
Questa funzione per i set di righe viene utilizzata per eseguire query relative alle informazioni sulle modifiche.This rowset function is used to query for change information. La funzione esegue una query sui dati archiviati nelle tabelle per il rilevamento delle modifiche interneThe function queries the data stored in the internal change tracking tables. e restituisce un set di risultati contenente le chiavi primarie delle righe modificate, insieme ad altre informazioni sulle modifiche, ad esempio l'operazione, le colonne aggiornate e la versione della riga.The function returns a results set that contains the primary keys of rows that have changed together with other change information such as the operation, columns updated and version for the row.

CHANGETABLE(CHANGES ...) accetta l'ultima versione sincronizzata come argomento.CHANGETABLE(CHANGES …) takes a last synchronization version as an argument. L'ultima versione sincronizzata si ottiene utilizzando la variabile @last_synchronization_version .The last sychronization version is obtained using the @last_synchronization_version variable. La semantica dell'ultima versione sincronizzata è la seguente:The semantics of the last synchronization version are as follows:

  • Il client chiamante ha ottenuto le modifiche e conosce tutte le modifiche fino all'ultima versione sincronizzata compresa.The calling client has obtained changes and knows about all changes up to and including the last synchronization version.

  • Tutte le modifiche eseguite dopo l'ultima versione sincronizzata verranno pertanto restituite in CHANGETABLE(CHANGES…).CHANGETABLE(CHANGES …) will therefore return all changes that have occurred after the last synchronization version.

    Nella figura seguente viene illustrato il modo in cui CHANGETABLE(CHANGES ...) viene utilizzata per ottenere modifiche.The following illustration shows how CHANGETABLE(CHANGES …) is used to obtain changes.

    Esempio di output della query per il rilevamento delle modificheExample of change tracking query output

    Funzione CHANGE_TRACKING_CURRENT_VERSION()CHANGE_TRACKING_CURRENT_VERSION() function
    Questa funzione viene utilizzata per ottenere la versione corrente che verrà utilizzata alla successiva esecuzione di query sulle modifiche.Is used to obtain the current version that will be used the next time when querying changes. Tale versione è quella relativa all'ultima transazione di cui è stato eseguito il commit.This version represents the version of the last committed transaction.

    Funzione CHANGE_TRACKING_MIN_VALID_VERSION()CHANGE_TRACKING_MIN_VALID_VERSION()function
    Questa funzione viene utilizzata per ottenere la versione minima valida che un client può avere per ottenere risultati validi da CHANGETABLE ().Is used to obtain the minimum valid version that a client can have and still obtain valid results from CHANGETABLE(). Il client deve controllare l'ultima versione sincronizzata rispetto al valore restituito dalla funzione.The client should check the last synchronization version against the value thatis returned by this function. Se l'ultima versione sincronizzata è inferiore rispetto a quella restituita dalla funzione, il client non sarà in grado di ottenere risultati validi da CHANGETABLE() e sarà necessario reinizializzare i dati.If the last synchronization version is less than the version returned by this function, the client will be unable to obtain valid results from CHANGETABLE() and will have to reinitialize.

Acquisizione dei dati inizialiObtaining Initial Data

Prima che un'applicazione sia in grado di ottenere modifiche per la prima volta, è necessario che invii una query per ottenere i dati iniziali e la versione sincronizzata.Before an application can obtain changes for the first time, the application must send a query to obtain the initial data and the synchronization version. È necessario che nell'applicazione vengano ottenuti i dati appropriati direttamente dalla tabella, quindi venga utilizzata CHANGE_TRACKING_CURRENT_VERSION() per ottenere la versione iniziale.The application must obtain the appropriate data directly from the table, and then use CHANGE_TRACKING_CURRENT_VERSION() to obtain the initial version. Tale versione verrà passata a CHANGETABLE(CHANGES ...) la prima volta che le modifiche vengono ottenute.This version will be passed to CHANGETABLE(CHANGES …) the first time that changes are obtained.

Nell'esempio seguente viene illustrato come ottenere la versione di sincronizzazione e il set di dati iniziali.The following example shows how to obtain the initial synchronization version and the initial data set.

    -- Obtain the current synchronization version. This will be used next time that changes are obtained.  
    SET @synchronization_version = CHANGE_TRACKING_CURRENT_VERSION();  

    -- Obtain initial data set.  
    SELECT  
        P.ProductID, P.Name, P.ListPrice  
    FROM  
        SalesLT.Product AS P  

Utilizzo delle funzioni di rilevamento delle modifiche per ottenere le modificheUsing the Change Tracking Functions to Obtain Changes

Per ottenere le righe modificate in una tabella e le relative informazioni, utilizzare CHANGETABLE(CHANGES ...).To obtain the changed rows for a table and information about the changes, use CHANGETABLE(CHANGES…). La query seguente, ad esempio, consente di ottenere le modifiche per la tabella SalesLT.Product .For example, the following query obtains changes for the SalesLT.Product table.

SELECT  
    CT.ProductID, CT.SYS_CHANGE_OPERATION,  
    CT.SYS_CHANGE_COLUMNS, CT.SYS_CHANGE_CONTEXT  
FROM  
    CHANGETABLE(CHANGES SalesLT.Product, @last_synchronization_version) AS CT  

Poiché in un client viene in genere richiesto di ottenere i dati più recenti relativi a una riga anziché le sole chiavi primarie per la riga stessa,Usually, a client will want to obtain the latest data for a row instead of only the primary keys for the row. verrà creato un join tra i risultati di CHANGETABLE(CHANGES ...) e i dati presenti nella tabella utente.Therefore, an application would join the results from CHANGETABLE(CHANGES …) with the data in the user table. Nella query seguente, ad esempio, viene creato un join con la tabella SalesLT.Product per ottenere i valori per le colonne Name e ListPrice .For example, the following query joins with the SalesLT.Product table to obtain the values for the Name and ListPrice columns. Si noti l'utilizzo di OUTER JOIN,Note the use of OUTER JOIN. necessario per garantire che le informazioni sulle modifiche vengano restituite per le righe eliminate dalla tabella utente.This is required to make sure that the change information is returned for those rows that have been deleted from the user table.

SELECT  
    CT.ProductID, P.Name, P.ListPrice,  
    CT.SYS_CHANGE_OPERATION, CT.SYS_CHANGE_COLUMNS,  
    CT.SYS_CHANGE_CONTEXT  
FROM  
    SalesLT.Product AS P  
RIGHT OUTER JOIN  
    CHANGETABLE(CHANGES SalesLT.Product, @last_synchronization_version) AS CT  
ON  
    P.ProductID = CT.ProductID  

Per ottenere la versione da utilizzare nella successiva enumerazione delle modifiche, utilizzare CHANGE_TRACKING_CURRENT_VERSION(), come illustrato nell'esempio seguente.To obtain the version for use in the next change enumeration, use CHANGE_TRACKING_CURRENT_VERSION(), as shown in the following example.

SET @synchronization_version = CHANGE_TRACKING_CURRENT_VERSION()  

Quando in un'applicazione vengono ottenute modifiche, è necessario utilizzare sia CHANGETABLE(CHANGES…) che CHANGE_TRACKING_CURRENT_VERSION(), come illustrato nell'esempio seguente.When an application obtains changes, it must use both CHANGETABLE(CHANGES…) and CHANGE_TRACKING_CURRENT_VERSION(), as shown in the following example.

-- Obtain the current synchronization version. This will be used the next time CHANGETABLE(CHANGES...) is called.  
SET @synchronization_version = CHANGE_TRACKING_CURRENT_VERSION();  

-- Obtain incremental changes by using the synchronization version obtained the last time the data was synchronized.  
SELECT  
    CT.ProductID, P.Name, P.ListPrice,  
    CT.SYS_CHANGE_OPERATION, CT.SYS_CHANGE_COLUMNS,  
    CT.SYS_CHANGE_CONTEXT  
FROM  
    SalesLT.Product AS P  
RIGHT OUTER JOIN  
    CHANGETABLE(CHANGES SalesLT.Product, @last_synchronization_version) AS CT  
ON  
    P.ProductID = CT.ProductID  

Numeri di versioneVersion Numbers

Un database in cui è abilitato il rilevamento delle modifiche dispone di un contatore di versione che aumenta in base alle modifiche apportate alle tabelle in cui il rilevamento è attivato.A database that has change tracking enabled has a version counter that increases as changes are made to change tracked tables. A ciascuna riga modificata è associato un numero di versione.Each changed row has a version number that is associated with it. Quando a un'applicazione viene inviata una richiesta per eseguire una query relativa alle modifiche, viene chiamata una funzione che specifica un numero di versione.When a request is sent to an application to query for changes, a function is called that supplies a version number. Tale funzione restituisce informazioni su tutte le modifiche apportate a partire da tale versione.The function returns information about all the changes that have been made since that version. Per alcuni aspetti, la versione del rilevamento delle modifiche è concettualmente analoga al tipo di dati rowversion .In some ways, change tracking version is similar in concept to the rowversion data type.

Convalida dell'ultima versione sincronizzataValidating the Last Synchronized Version

Le informazioni sulle modifiche vengono mantenute per un periodo di tempo limitato,Information about changes is maintained for a limited time. la cui lunghezza viene controllata dal parametro CHANGE_RETENTION che può essere specificato nell'istruzione ALTER DATABASE.The length of time is controlled by the CHANGE_RETENTION parameter that can be specified as part of the ALTER DATABASE.

È necessario tenere presente che il periodo di tempo specificato per CHANGE_RETENTION determina la frequenza con cui per tutte le applicazioni è necessario richiedere le modifiche apportate al database.Be aware that the time specified for CHANGE_RETENTION determines how frequently all applications must request changes from the database. Se a un'applicazione è associato un valore relativo a last_synchronization_version meno recente rispetto a quello della versione sincronizzata valida minima per una tabella, tale applicazione non può eseguire un'enumerazione delle modifiche valida.If an application has a value for last_synchronization_version that is older than the minimum valid synchronization version for a table, that application cannot perform valid change enumeration. poiché alcune informazioni sulle modifiche potrebbero essere state eliminate.This is because some change information might have been cleaned up. Affinché in un'applicazione possano essere ottenute le modifiche tramite CHANGETABLE(CHANGES …), è necessario che venga convalidato il valore relativo a last_synchronization_version di cui è previsto il passaggio a CHANGETABLE(CHANGES …).Before an application obtains changes by using CHANGETABLE(CHANGES …), the application must validate the value for last_synchronization_version that it plans to pass to CHANGETABLE(CHANGES …). Se il valore di last_synchronization_version non è valido, è necessario che nell'applicazione vengano reinizializzati tutti i dati.If the value of last_synchronization_version is not valid, that application must reinitialize all the data.

Nell'esempio seguente viene illustrato come verificare la validità del valore di last_synchronization_version per ogni tabella.The following example shows how to verify the validity of the value of last_synchronization_version for each table.

-- Check individual table.  
IF (@last_synchronization_version < CHANGE_TRACKING_MIN_VALID_VERSION(  
                                   OBJECT_ID('SalesLT.Product')))  
BEGIN  
  -- Handle invalid version and do not enumerate changes.  
  -- Client must be reinitialized.  
END  

Come illustrato nell'esempio seguente, la validità del valore di last_synchronization_version può essere verificata in relazione a tutte le tabelle del database.As the following example shows, the validity of the value of last_synchronization_version can be checked against all tables in the database.

-- Check all tables with change tracking enabled  
IF EXISTS (  
  SELECT COUNT(*) FROM sys.change_tracking_tables  
  WHERE min_valid_version > @last_synchronization_version )  
BEGIN  
  -- Handle invalid version & do not enumerate changes  
  -- Client must be reinitialized  
END  

Utilizzo del rilevamento a livello di colonnaUsing Column Tracking

Il rilevamento a livello di colonna consente di ottenere i dati relativi alle sole colonne modificate anziché all'intera riga.Column tracking enables applications to obtain the data for only the columns that have changed instead of the whole row. Si consideri ad esempio uno scenario in cui in una tabella sono presenti una o più colonne di notevoli dimensioni, ma modificate raramente, e altre colonne che subiscono modifiche frequenti.For example, consider the scenario in which a table has one or more columns that are large, but rarely change; and also has other columns that frequently change. Senza il rilevamento a livello di colonna, un'applicazione è in grado di rilevare solo che una riga è stata modificata e che è necessario sincronizzare tutti i dati, inclusi quelli presenti nelle colonne di grandi dimensioni.Without column tracking, an application can only determine that a row has changed and would have to synchronize all the data that includes the large column data. Il rilevamento a livello di colonna consente tuttavia di stabilire se i dati presenti nelle colonne di grandi dimensioni sono stati modificati e di eseguire la sincronizzazione solo in quest'ultimo caso.However, by using column tracking, an application can determine whether the large column data changed and only synchronize the data if it has changed.

Le informazioni sul rilevamento a livello di colonna vengono visualizzate nella colonna SYS_CHANGE_COLUMNS restituita dalla funzione CHANGETABLE(CHANGES …).Column tracking information appears in the SYS_CHANGE_COLUMNS column that is returned by the CHANGETABLE(CHANGES …) function.

Il rilevamento a livello di colonna può essere utilizzato in modo che per una colonna cui non sono state apportate modifiche venga restituito il valore NULL.Column tracking can be used so that NULL is returned for a column that has not changed. Se la colonna può essere impostata su NULL, è necessario che venga restituita una colonna separata per indicare se la colonna è stata modificata.If the column can be changed to NULL, a separate column must be returned to indicate whether the column changed.

Nell'esempio seguente se la colonna CT_ThumbnailPhoto non ha subito modifiche, verrà restituito il valore NULL .In the following example, the CT_ThumbnailPhoto column will be NULL if that column did not change. A tale colonna potrebbe inoltre essere associato il valore NULL poiché è stata impostata su NULL . È possibile utilizzare la colonna CT_ThumbNailPhoto_Changed per determinare se la colonna ha subito modifiche.This column could also be NULL because it was changed to NULL - the application can use the CT_ThumbNailPhoto_Changed column to determine whether the column changed.

DECLARE @PhotoColumnId int = COLUMNPROPERTY(  
    OBJECT_ID('SalesLT.Product'),'ThumbNailPhoto', 'ColumnId')  

SELECT  
    CT.ProductID, P.Name, P.ListPrice, -- Always obtain values.  
    CASE  
           WHEN CHANGE_TRACKING_IS_COLUMN_IN_MASK(  
                     @PhotoColumnId, CT.SYS_CHANGE_COLUMNS) = 1  
            THEN ThumbNailPhoto  
            ELSE NULL  
      END AS CT_ThumbNailPhoto,  
      CHANGE_TRACKING_IS_COLUMN_IN_MASK(  
                     @PhotoColumnId, CT.SYS_CHANGE_COLUMNS) AS  
                                   CT_ThumbNailPhoto_Changed  
     CT.SYS_CHANGE_OPERATION, CT.SYS_CHANGE_COLUMNS,  
     CT.SYS_CHANGE_CONTEXT  
FROM  
     SalesLT.Product AS P  
INNER JOIN  
     CHANGETABLE(CHANGES SalesLT.Product, @last_synchronization_version) AS CT  
ON  
     P.ProductID = CT.ProductID AND  
     CT.SYS_CHANGE_OPERATION = 'U'  

Acquisizione di risultati coerenti e correttiObtaining Consistent and Correct Results

Per ottenere i dati modificati relativi a una tabella, è necessario effettuare più operazioni.Obtaining the changed data for a table requires multiple steps. È necessario inoltre tenere presente che potrebbero venire restituiti risultati incoerenti o non corretti se non vengono considerati e gestiti problemi specifici.Be aware that inconsistent or incorrect results could be returned if certain issues are not considered and handled.

Per ottenere le modifiche apportate a una tabella Sales e a una tabella SalesOrders, in un'applicazione è necessario ad esempio effettuare le operazioni seguenti:For example, to obtain the changes that were made to a Sales table and SalesOrders table, an application would perform the following steps:

  1. Convalidare l'ultima versione sincronizzata utilizzando CHANGE_TRACKING_MIN_VALID_VERSION().Validate the last synchronized version by using CHANGE_TRACKING_MIN_VALID_VERSION().

  2. Ottenere la versione che può essere utilizzata per ottenere le modifiche la volta successiva utilizzando CHANGE_TRACKING_CURRENT_VERSION().Obtain the version that can be used to obtain change the next time by using CHANGE_TRACKING_CURRENT_VERSION().

  3. Ottenere le modifiche per la tabella Sales utilizzando CHANGETABLE(CHANGES …).Obtain the changes for the Sales table by using CHANGETABLE(CHANGES …).

  4. Ottenere le modifiche per la tabella SalesOrders utilizzando CHANGETABLE(CHANGES …).Obtain the changes for the SalesOrders table by using CHANGETABLE(CHANGES …).

    Nel database sono in esecuzione due processi che possono influenzare i risultati restituiti dalle operazioni precedenti:Two processes are occurring in the database that can affect the results that are returned by the previous steps:

  • Il processo di pulizia viene eseguito in background e rimuove le informazioni sul rilevamento delle modifiche precedenti rispetto al periodo di memorizzazione specificato.The cleanup process runs in the background and removes change tracking information that is older than the specified retention period.

    Il processo di pulizia è un processo eseguito separatamente in background che utilizza il periodo di memorizzazione specificato quando si configura il rilevamento delle modifiche per il database.The cleanup process is a separate background process that uses the retention period that is specified when you configure change tracking for the database. Quando il processo di pulizia viene eseguito nel periodo di tempo che intercorre tra la convalida dell'ultima versione sincronizzata e la chiamata di funzione CHANGETABLE(CHANGES ...), può verificarsi un problemaThe issue is that the cleanup process can occur in the time between when the last synchronization version was validated and when the call to CHANGETABLE(CHANGES…) is made. poiché l'ultima versione sincronizzata valida potrebbe non esserlo più nel momento in cui vengono ottenute le modifiche.A last synchronization version that was just valid might no longer be valid by the time the changes are obtained. È possibile pertanto che vengano restituiti risultati non corretti.Therefore, incorrect results might be returned.

  • Operazioni DML in corso nelle tabelle Sales e SalesOrders, ad esempio le operazioni seguenti:Ongoing DML operations are occurring in the Sales and SalesOrders tables, such as the following operations:

    • Esecuzione di modifiche alle tabelle dopo che è stata ottenuta la versione per la volta successiva mediante CHANGE_TRACKING_CURRENT_VERSION().Changes can be made to the tables after the version for next time has been obtained by using CHANGE_TRACKING_CURRENT_VERSION(). È pertanto possibile che vengano restituite più modifiche del previsto.Therefore, more changes can be returned than expected.

    • Esecuzione del commit di una transazione nel periodo di tempo che intercorre tra la chiamata di funzione per ottenere le modifiche apportate alla tabella Sales e quella per ottenere le modifiche apportate alla tabella SalesOrders.A transaction could commit in the time between the call to obtain changes from the Sales table and the call to obtain changes from the SalesOrders table. Ai risultati relativi alla tabella SalesOrder potrebbe pertanto essere associato un valore di chiave esterna che non esiste nella tabella Sales.Therefore, the results for the SalesOrder table could have foreign key value that does not exist in the Sales table.

    Per risolvere i problemi elencati in precedenza, è consigliabile utilizzare l'isolamento dello snapshotTo overcome the previously listed challenges, we recommend that you use snapshot isolation. che consente di garantire la coerenza delle informazioni sulle modifiche e di evitare situazioni di race condition correlate all'attività di pulizia eseguita in background.This will help to ensure consistency of change information and avoid race conditions that are related to the background cleanup task. Se non si utilizzano transazioni snapshot, lo sviluppo di un'applicazione che utilizza il rilevamento delle modifiche potrebbe risultare notevolmente più impegnativo.If you do not use snapshot transactions, developing an application that uses change tracking could require significantly more effort.

Utilizzo dell'isolamento dello snapshotUsing Snapshot Isolation

Il rilevamento delle modifiche è stato progettato per funzionare in modo ottimale con l'isolamento dello snapshot.Change tracking has been designed to work well with snapshot isolation. È necessario che l'isolamento dello snapshot sia abilitato nel database.Snapshot isolation must be enabled for the database. Tutti i passaggi necessari per ottenere le modifiche devono essere contenuti in una transazione snapshotAll the steps that are required to obtain changes must be included inside a snapshot transaction. in modo che tutte le modifiche apportate ai dati durante l'acquisizione delle modifiche stesse non siano visibili alle query eseguite nella transazione snapshot.This will ensure that all changes that are made to data while obtaining changes will not be visible to the queries inside the snapshot transaction.

Per ottenere dati all'interno di una transazione snapshot, effettuare le operazioni seguenti:To obtain data inside a snapshot transaction, perform the following steps:

  1. Impostare il livello di isolamento della transazione sullo snapshot e avviare una transazione.Set the transaction isolation level to snapshot and start a transaction.

  2. Convalidare l'ultima versione sincronizzata utilizzando CHANGE_TRACKING_MIN_VALID_VERSION().Validate the last synchronization version by using CHANGE_TRACKING_MIN_VALID_VERSION().

  3. Ottenere la versione da utilizzare successivamente tramite CHANGE_TRACKING_CURRENT_VERSION().Obtain the version to be used the next time by using CHANGE_TRACKING_CURRENT_VERSION().

  4. Ottenere le modifiche per la tabella Sales utilizzando CHANGETABLE(CHANGES …).Obtain the changes for the Sales table by using CHANGETABLE(CHANGES …)

  5. Ottenere le modifiche per la tabella SalesOrders utilizzando CHANGETABLE(CHANGES …).Obtain the changes for the Salesorders table by using CHANGETABLE(CHANGES …)

  6. Eseguire il commit della transazione.Commit the transaction.

    Poiché tutti i passaggi necessari per ottenere le modifiche sono contenuti in una transazione snapshot, tenere in considerazione quanto segue:Some points to remember as all steps to obtain changes are inside a snapshot transaction:

  • Se il processo di pulizia viene eseguito dopo la convalida dell'ultima versione sincronizzata, i risultati restituiti da CHANGETABLE(CHANGES …) saranno ancora validi poiché le operazioni di eliminazione eseguite dal processo di pulizia non saranno visibili all'interno della transazione.If cleanup occurs after the last synchronization version is validated, the results from CHANGETABLE(CHANGES …) will still be valid as the delete operations performed by cleanup will not be visible inside the transaction.

  • Qualsiasi modifica apportata alla tabella Sales o SalesOrders dopo che è stata ottenuta la versione sincronizzata successiva non sarà visibile e le chiamate a CHANGETABLE(CHANGES …) non restituiranno mai modifiche con una versione successiva a quella restituita da CHANGE_TRACKING_CURRENT_VERSION().Any changes that are made to the Sales table or the SalesOrders table after the next synchronization version is obtained will not be visible, and the calls to CHANGETABLE(CHANGES …) will never return changes with a version later than that returned by CHANGE_TRACKING_CURRENT_VERSION(). Verrà inoltre mantenuta la coerenza tra le tabelle Sales e SalesOrders poiché le transazioni di cui era stato eseguito il commit nel periodo di tempo che intercorre tra le chiamate a CHANGETABLE(CHANGES …) non saranno visibili.Consistency between the Sales table and the SalesOrders table will also be maintained, because the transactions that were committed in the time between calls to CHANGETABLE(CHANGES …) will not be visible.

    Nell'esempio seguente viene illustrato il modo in cui l'isolamento dello snapshot viene abilitato per un database.The following example shows how snapshot isolation is enabled for a database.

-- The database must be configured to enable snapshot isolation.  
ALTER DATABASE AdventureWorksLT  
    SET ALLOW_SNAPSHOT_ISOLATION ON;  

Una transazione snapshot viene utilizzata nel modo seguente:A snapshot transaction is used as follows:

SET TRANSACTION ISOLATION LEVEL SNAPSHOT;  
BEGIN TRAN  
  -- Verify that version of the previous synchronization is valid.  
  -- Obtain the version to use next time.  
  -- Obtain changes.  
COMMIT TRAN  

Per altre informazioni sulle transazioni snapshot, vedere SET TRANSACTION ISOLATION LEVEL (Transact-SQL).For more information about snapshot transactions, see SET TRANSACTION ISOLATION LEVEL (Transact-SQL).

Alternative all'utilizzo dell'isolamento dello snapshotAlternatives to Using Snapshot Isolation

Oltre all'isolamento dello snapshot, è possibile utilizzare metodi alternativi che tuttavia richiedono l'esecuzione di un numero maggiore di operazioni per garantire che tutti i requisiti relativi all'applicazione siano soddisfatti.There are alternatives to using snapshot isolation, but they require more work to make sure all application requirements are met. Per garantire che il valore di last_synchronization_version sia valido e che i dati non vengano rimossi dal processo di pulizia prima dell'acquisizione delle modifiche, eseguire le operazioni seguenti:To make sure the last_synchronization_version is valid and data is not removed by the cleanup process before changes are obtained, do the following:

  1. Verificare il valore di last_synchronization_version dopo le chiamate a CHANGETABLE ().Check last_synchronization_version after the calls to CHANGETABLE().

  2. Verificare il valore di last_synchronization_version come parte di ogni query per ottenere le modifiche tramite CHANGETABLE().Check last_synchronization_version as part of each query to obtain changes by using CHANGETABLE().

    È possibile che vengano eseguite modifiche dopo che è stata ottenuta la versione sincronizzata per l'enumerazione successiva.Changes can occur after the synchronization version for the next enumeration has been obtained. Questa situazione può essere gestita in due modi diversi.There are two ways to handle this situation. L'approccio utilizzato dipende dall'applicazione e dalla modalità di gestione degli effetti collaterali associati a ciascun approccio:The option that is used depends on the application and how it can handle the side-effects of each approach:

  • Ignorare le modifiche con versione superiore rispetto alla nuova versione sincronizzata.Ignore changes that have a version larger than the new synchronization version.

    In base a questo approccio, verrà ignorata ogni riga nuova o aggiornata creata o aggiornata prima delle nuove versioni sincronizzate, ma aggiornata in seguito.This approach has the side effect that a new or updated row would be skipped if it was created or updated before the new synchronization version, but then updated afterward. Se è presente una nuova riga, potrebbe verificarsi un problema di integrità referenziale se in un'altra tabella era stata creata una riga che faceva riferimento alla riga ignorata.If there is a new row, a referential integrity problem might occur if there was a row in another table that was created that referenced the skipped row. Se è presente una riga aggiornata, tale riga verrà ignorata e non verrà sincronizzata fino alla volta successiva.If there is an updated existing row, the row will be skipped and not synchronized until the next time.

  • Includere tutte le modifiche, anche quelle con versione superiore rispetto alla nuova versione sincronizzata.Include all changes, even those that have a version larger than the new synchronization version.

    Le righe con versione superiore alla nuova versione sincronizzata verranno ottenute anche alla sincronizzazione successiva.The rows that have a version larger than the new synchronization version will be obtained again on the next synchronization. Questa situazione deve essere prevista e gestita dall'applicazione.This must be expected and handled by the application.

    Oltre ai due approcci precedenti, è possibile definirne altri che utilizzino entrambe le opzioni, in base all'operazione.In addition to the previous two options, you can devise approach that combines both options, depending on the operation. Potrebbe ad esempio essere necessario utilizzare un'applicazione per cui è preferibile ignorare le modifiche più recenti rispetto alla versione sincronizzata successiva in cui la riga è stata creata o eliminata, ma per cui gli aggiornamenti non vengono ignorati.For example, you might want an application for which it is best to ignore changes newer than the next synchronization version in which the row was created or deleted, but updates are not ignored.

Nota

Poiché la scelta dell'approccio più efficiente per l'applicazione quando si utilizza il rilevamento delle modifiche o qualsiasi meccanismo di rilevamento personalizzato richiede l'esecuzione di un'analisi approfondita,Choosing the approach that will work for the application when you are using change tracking (or any custom tracking mechanism), requires significant analysis. l'utilizzo dell'isolamento dello snapshot è notevolmente più semplice.Therefore, it is much simpler to use snapshot isolation.

Gestione delle modifiche in un database da parte del rilevamento delle modifiche How Change Tracking Handles Changes to a Database

Alcune applicazioni che utilizzano il rilevamento delle modifiche eseguono la sincronizzazione bidirezionale con un altro archivio dati.Some applications that use change tracking perform two-way synchronization with another data store. Questo significa che le modifiche apportate al database di SQL ServerSQL Server vengono aggiornate nell'altro archivio dati, mentre le modifiche apportate all'archivio vengono aggiornate nel database di SQL ServerSQL Server .That is, changes that are made in the SQL ServerSQL Server database are updated in the other data store, and changes that are made in the other store are updated in the SQL ServerSQL Server database.

Quando aggiorna il database locale in base alle modifiche di un altro archivio dati, un'applicazione deve effettuare le operazioni seguenti:When an application updates the local database with changes from another data store, the application must perform the following operations:

  • Verificare la presenza di conflitti.Check for conflicts.

    Un conflitto si verifica quando gli stessi dati vengono modificati contemporaneamente in entrambi gli archivi dati.A conflict occurs when the same data is changed at the same time in both data stores. L'applicazione deve essere in grado di verificare la presenza di un conflitto e di ottenere informazioni sufficienti per consentirne la risoluzione.The application must be able to check for a conflict and obtain enough information to enable the conflict to be resolved.

  • Archiviare le informazioni sul contesto dell'applicazione.Store application context information.

    L'applicazione archivia i dati che dispongono di informazioni sul rilevamento delle modifiche.The application stores data that has the change tracking information. Dopo che le modifiche sono state ottenute dal database locale, tali informazioni saranno disponibili con altre informazioni sul rilevamento delle modifiche.This information would be available together with other change tracking information when changes were obtained from the local database. Un esempio comune di tali informazioni contestuali è rappresentato da un identificatore per l'archivio dati che costituiva l'origine della modifica.A common example of this contextual information is an identifier for the data store that was the source of the change.

    Per eseguire le operazioni precedenti, un'applicazione di sincronizzazione può utilizzare le funzioni seguenti:To perform the previous operations, a synchronization application can use the following functions:

  • CHANGETABLE(VERSION…)CHANGETABLE(VERSION…)

    Quando un'applicazione apporta modifiche, può utilizzare questa funzione per verificare la presenza di conflitti.When an application is making changes, it can use this function to check for conflicts. La funzione ottiene le informazioni sul rilevamento delle modifiche più recenti per una riga specificata in una tabella con rilevamento.The function obtains the latest change tracking information for a specified row in a change tracked table. In tali informazioni è inclusa la versione della riga in cui è stata eseguita l'ultima modifica.The change tracking information includes the version of the row that was last changed. Questa informazione consente a un'applicazione di determinare se la riga è stata modificata dopo l'ultima sincronizzazione dell'applicazione stessa.This information enables an application to determine whether the row was changed after the last time that the application was synchronized.

  • WITH CHANGE_TRACKING_CONTEXTWITH CHANGE_TRACKING_CONTEXT

    Un'applicazione può utilizzare questa clausola per archiviare dati relativi al contesto.An application can use this clause to store context data.

Verifica della presenza di conflittiChecking for Conflicts

In uno scenario di sincronizzazione bidirezionale l'applicazione client deve determinare se una riga non è stata aggiornata dall'ultima volta in cui l'applicazione ha ottenuto le modifiche.In a two-way synchronization scenario, the client application must determine whether a row has not been updated since the application last obtained the changes.

Nell'esempio seguente viene illustrato come utilizzare la funzione CHANGETABLE(VERSION ...) per verificare la presenza di conflitti nel modo più efficiente, senza eseguire una query separata.The following example shows how to use the CHANGETABLE(VERSION …) function to check for conflicts in the most efficient way, without a separate query. Nell'esempio, CHANGETABLE(VERSION …) determina SYS_CHANGE_VERSION per la riga specificata da @product id.In the example, CHANGETABLE(VERSION …) determines the SYS_CHANGE_VERSION for the row specified by @product id. CHANGETABLE(CHANGES …) può ottenere le stesse informazioni, ma sarebbe meno efficiente.CHANGETABLE(CHANGES …) can obtain the same information, but that would be less efficient. Se il valore di SYS_CHANGE_VERSION per la riga è maggiore del valore di @last_sync_version, si verifica un conflitto.If the value of SYS_CHANGE_VERSION for the row is larger than the value of @last_sync_version, there is a conflict. In questo caso la riga non verrà aggiornata.If there is a conflict, the row will not be updated. Il controllo ISNULL() è necessario perché per la riga potrebbero non essere disponibili informazioni sulle modifiche.The ISNULL() check is required because there might be no change information available for the row. Nel caso in cui la riga non sia stata aggiornata dal momento in cui è stato abilitato il rilevamento delle modifiche o dal momento in cui le informazioni sulle modifiche sono state eliminate, non sarebbe infatti disponibile alcuna informazione sulle modifiche.No change information would exist if the row had not been updated since change tracking was enabled or since the change information was cleaned up.

-- Assumption: @last_sync_version has been validated.  

UPDATE  
    SalesLT.Product  
SET  
    ListPrice = @new_listprice  
FROM  
    SalesLT.Product AS P  
WHERE  
    ProductID = @product_id AND  
    @last_sync_version >= ISNULL (  
        SELECT CT.SYS_CHANGE_VERSION  
        FROM CHANGETABLE(VERSION SalesLT.Product,  
                        (ProductID), (P.ProductID)) AS CT),  
        0)  

Il codice seguente consente di controllare il conteggio delle righe aggiornate e di identificare ulteriori informazioni sul conflitto.The following code can check the updated row count and can identify more information about the conflict.

-- If the change cannot be made, find out more information.  
IF (@@ROWCOUNT = 0)  
BEGIN  
    -- Obtain the complete change information for the row.  
    SELECT  
        CT.SYS_CHANGE_VERSION, CT.SYS_CHANGE_CREATION_VERSION,  
        CT.SYS_CHANGE_OPERATION, CT.SYS_CHANGE_COLUMNS  
    FROM  
        CHANGETABLE(CHANGES SalesLT.Product, @last_sync_version) AS CT  
    WHERE  
        CT.ProductID = @product_id;  

    -- Check CT.SYS_CHANGE_VERSION to verify that it really was a conflict.  
    -- Check CT.SYS_CHANGE_OPERATION to determine the type of conflict:  
    -- update-update or update-delete.  
    -- The row that is specified by @product_id might no longer exist   
    -- if it has been deleted.  
END  

Impostazione delle informazioni sul contestoSetting Context Information

Utilizzando la clausola WITH CHANGE_TRACKING_CONTEXT un'applicazione può archiviare le informazioni sul contesto con le informazioni sulle modifiche.By using the WITH CHANGE_TRACKING_CONTEXT clause, an application can store context information together with the change information. Tali informazioni possono quindi essere ottenute dalla colonna SYS_CHANGE_CONTEXT restituita da CHANGETABLE(CHANGES ...).This information can then be obtained from the SYS_CHANGE_CONTEXT column that is returned by CHANGETABLE(CHANGES …).

Le informazioni sul contesto vengono utilizzate in genere per identificare l'origine delle modifiche.Context information is typically used to identify the source of the changes. Se è possibile identificare l'origine della modifica, tali informazioni possono essere utilizzate da un archivio dati per evitare di ottenere modifiche alla successiva sincronizzazione.If the source of the change can be identified, that information can be used by a data store to avoid obtaining changes when it synchronizes again.

  -- Try to update the row and check for a conflict.  
  WITH CHANGE_TRACKING_CONTEXT (@source_id)  
  UPDATE  
     SalesLT.Product  
  SET  
      ListPrice = @new_listprice  
  FROM  
      SalesLT.Product AS P  
  WHERE  
     ProductID = @product_id AND  
     @last_sync_version >= ISNULL (  
         (SELECT CT.SYS_CHANGE_VERSION FROM CHANGETABLE(VERSION SalesLT.Product,  
         (ProductID), (P.ProductID)) AS CT),  
         0)  

Come garantire risultati coerenti e correttiEnsuring Consistent and Correct Results

Al momento della convalida del valore di @last_sync_version, è necessario che in un'applicazione venga considerato il processo di puliziaAn application must consider the cleanup process when it validates the value of @last_sync_version.</span></span> poiché i dati potrebbero essere stati rimossi i dati dopo la chiamata a CHANGE_TRACKING_MIN_VALID_VERSION (), ma prima che sia stato eseguito l'aggiornamento.This is because data could have been removed after CHANGE_TRACKING_MIN_VALID_VERSION() was called, but before the update was made.

Importante

È consigliabile utilizzare l'isolamento dello snapshot e apportare le modifiche all'interno di una transazione snapshot.We recommend that you use snapshot isolation and make the changes within a snapshot transaction.

-- Prerequisite is to ensure ALLOW_SNAPSHOT_ISOLATION is ON for the database.  

SET TRANSACTION ISOLATION LEVEL SNAPSHOT;  
BEGIN TRAN  
    -- Verify that last_sync_version is valid.  
    IF (@last_sync_version <  
CHANGE_TRACKING_MIN_VALID_VERSION(OBJECT_ID(‘SalesLT.Product’)))  
    BEGIN  
       RAISERROR (N’Last_sync_version too old’, 16, -1);  
    END  
    ELSE  
    BEGIN  
        -- Try to update the row.  
        -- Check @@ROWCOUNT and check for a conflict.  
    END  
COMMIT TRAN  

Nota

È possibile che la riga in fase di aggiornamento all'interno della transazione snapshot sia stata aggiornata in un'altra transazione dopo l'avvio della transazione stessa.There is a possibility that the row being updated within the snapshot transaction could have been updated in another transaction after the snapshot transaction was started. In questo caso, si verifica un conflitto nell'aggiornamento dell'isolamento dello snapshot e la transazione verrà terminata.In this case, a snapshot isolation update conflict will occur and lead to the transaction being terminated. Se si verifica questa situazione, riprovare a eseguire l'aggiornamento.If this happens, retry the update. In questo modo verrà individuato un conflitto nel rilevamento delle modifiche e nessuna riga verrà modificata.This will then lead to a change tracking conflict being detected and no rows being changed.

Rilevamento delle modifiche e ripristino dei dati Change Tracking and Data Restore

Le applicazioni che richiedono la sincronizzazione è necessario considerare il caso in cui un database con il rilevamento delle modifiche abilitato viene ripristinato a una versione precedente dei dati.Applications that require synchronization must consider the case in which a database that has change tracking enabled reverts to an earlier version of the data. Questa situazione può verificarsi dopo il ripristino di un database da un backup, quando si verifica un failover a un database mirror asincrono o quando si verifica un errore durante l'utilizzo del log shipping.This can occur after a database is restored from a backup, when there is a failover to an asynchronous database mirror, or when there is a failure when using log shipping. Nel seguente scenario viene illustrato il problema:The following scenario illustrates the issue:

  1. Nella tabella T1 è attivato il rilevamento delle modifiche e la versione minima valida della tabella è 50.Table T1 is change tracked, and the minimum valid version for table is 50.

  2. Un'applicazione client sincronizza i dati alla versione 100 e ottiene informazioni su tutte le modifiche tra le versioni 50 e 100.A client application synchronizes data at version 100 and obtains information about all changes between versions 50 and 100.

  3. Le modifiche aggiuntive vengono apportate alla tabella T1 dopo la versione 100.Additional changes are made to table T1 after version 100.

  4. Alla versione 120 si verifica un errore e l'amministratore del database ripristina il database con perdita di dati.At version 120, there is a failure and the database administrator restores the database with data loss. Dopo l'operazione di ripristino, la tabella contiene dati fino alla versione 70 e la versione minima sincronizzata è ancora 50.After the restore operation, the table contains data up through version 70, and the minimum synchronized version is still 50.

    Ciò significa che l'archivio dati sincronizzato ha dati che non esistono più nell'archivio dati primario.This means that the synchronized data store has data that no longer exists in the primary data store.

  5. T1 viene aggiornato molte volte.T1 is updated many times. La versione corrente viene portata a 130.This brings the current version to 130.

  6. L'applicazione client esegue nuovamente la sincronizzazione e fornisce l'ultima versione sincronizzata: 100.The client application synchronizes again and supplies a last-synchronized version of 100. Il client convalida il numero, in quanto 100 è maggiore di 50.The client validates this number successfully because 100 is greater than 50.

    Il client ottiene le modifiche tra la versione 100 e la 130.The client obtains changes between version 100 and 130. A questo punto, il client non riconosce che le modifiche tra 70 e 100 non sono come le modifiche precedenti.At this point, the client is not aware that the changes between 70 and 100 are not the same as before. I dati nel client e nel server non sono sincronizzati.The data on the client and server are not synchronized.

    Se il database è stato recuperato in un punto successivo alla versione 100, non si verificheranno problemi con la sincronizzazione.Note that if the database was recovered to a point after version 100, there would be no problems with synchronization. Il client e il server sincronizzeranno correttamente i dati durante il successivo intervallo di sincronizzazione.The client and server would synchronize data correctly during the next synchronization interval.

    Il rilevamento delle modifiche non fornisce il supporto per il recupero dalla perdita di dati.Change tracking does not provide support for recovering from the loss of data. Tuttavia, sono disponibili due opzioni per il rilevamento di questi tipi di problemi di sincronizzazione:However, there are two options for detecting these types of synchronization issues:

  • Archiviare un ID della versione del database nel server e aggiornare tale valore ogni volta che un database viene recuperato o perde dati.Store a database version ID on the server, and update this value whenever a database is recovered or otherwise loses data. Ciascuna applicazione client archivia l'ID e ciascun client convalida tale ID quando viene eseguita la sincronizzazione dei dati.Each client application would store the ID, and each client would have to validate this ID when it synchronizes data. Se si verifica la perdita di dati, gli ID non corrisponderanno e i client verranno reinizializzati.If data loss occurs, the IDs will not match and the clients would reinitialize. Se la perdita di dati non si sovrappone all'ultimo limite di date sincronizzato, il client potrebbe essere reinizializzato inutilmente.One drawback is if the data loss had not crossed the last synchronized boundary, the client might do unnecessary reinitialization.

  • Quando un client esegue una query per le modifiche, registrare il numero dell'ultima versione sincronizzata per ciascun client nel server.When a client queries for changes, record the last synchronization version number for each client on the server. Se si verifica un problema con i dati, i numeri delle ultime versioni sincronizzate non corrispondono.If there is a problem with the data, the last synchronized version numbers would not match. Ciò indica che è necessario eseguire la reinizializzazione.This indicates that a reinitialization is required.

Vedere ancheSee Also

Tenere traccia delle modifiche ai dati (SQL Server) Track Data Changes (SQL Server)
Informazioni sul rilevamento delle modifiche (SQL Server) About Change Tracking (SQL Server)
Gestire il rilevamento delle modifiche (SQL Server) Manage Change Tracking (SQL Server)
Abilitare e disabilitare il rilevamento delle modifiche (SQL Server) Enable and Disable Change Tracking (SQL Server)
CHANGETABLE (Transact-SQL) CHANGETABLE (Transact-SQL)
CHANGE_TRACKING_MIN_VALID_VERSION (Transact-SQL) CHANGE_TRACKING_MIN_VALID_VERSION (Transact-SQL)
CHANGE_TRACKING_CURRENT_VERSION (Transact-SQL) CHANGE_TRACKING_CURRENT_VERSION (Transact-SQL)
WITH CHANGE_TRACKING_CONTEXT (Transact-SQL) WITH CHANGE_TRACKING_CONTEXT (Transact-SQL)