Utiliser le suivi des modifications (SQL Server)

S’applique à :SQL ServerAzure SQL DatabaseAzure SQL Managed Instance

Les applications qui utilisent le suivi des modifications doivent être en mesure d'obtenir les modifications suivies, d'appliquer ces modifications à une autre banque de données et de mettre à jour la base de données source. Cet article explique comment effectuer ces tâches, ainsi que le suivi des modifications de rôle joue lorsqu’un basculement se produit et qu’une base de données doit être restaurée à partir d’une sauvegarde.

Obtenir les modifications à l'aide des fonctions de suivi des modifications

Explique comment utiliser les fonctions de suivi des modifications pour obtenir des modifications et les informations sur les modifications apportées à une base de données.

À propos des fonctions de suivi des modifications

Les applications peuvent utiliser les fonctions suivantes pour obtenir les modifications apportées à une base de données et les informations concernant ces modifications.

Fonction CHANGETABLE(CHANGES ...)
Cette fonction d'ensemble de lignes permet d'exécuter des requêtes d'informations de modifications. Elle interroge les données stockées dans les tables de suivi des modifications internes. Elle renvoie un jeu de résultats qui contient les clés primaires des lignes qui ont changé, ainsi que d'autres informations de modification telles que l'opération, les colonnes mises à jour et la version de la ligne.

La fonction CHANGETABLE(CHANGES ...) prend une dernière version de synchronisation comme argument. La dernière version de synchronisation est obtenue à l'aide de la variable @last_synchronization_version. La sémantique de la dernière version de synchronisation est la suivante :

  • Le client appelant a obtenu les modifications et connaît toutes les modifications jusqu'à la dernière version de synchronisation comprise.

  • La fonction CHANGETABLE(CHANGES ...) retourne par conséquent toutes les modifications qui se sont produites après la dernière version de synchronisation.

    L’illustration suivante montre comment CHANGETABLE(CHANGES ...) est utilisée pour obtenir des modifications.

    Diagram that shows an example of change tracking query output.

    Dans cet exemple, le client A a été synchronisé à 9 h 30, tandis que le client B a été synchronisé pour la dernière fois à 10 h 30. À 10h00 et à nouveau à 11h00, plusieurs modifications ont été apportées aux données. Ces modifications suivies sont résumées ci-dessous.

    CHANGETABLE(CHANGES...) Sortie - 11h30

    Client Un dernier synchronisé à 9 h 30.

    ID de produit Operation Colonnes
    139 Update Nom, Prix
    140 DELETE -
    141 Insérer -

    Le client B a été synchronisé pour la dernière fois à 10 h 30.

    ID de produit Operation Colonnes
    139 Update Tarif
    140 DELETE -
    141 Update Tarif

Fonction CHANGE_TRACKING_CURRENT_VERSION()
Permet d’obtenir la version actuelle qui sera utilisée la prochaine fois lors de l’interrogation des modifications. Cette version représente la version de la dernière transaction validée.

Fonction CHANGE_TRACKING_MIN_VALID_VERSION()
Utilisé pour obtenir la version minimale valide qu’un client peut avoir et toujours obtenir des résultats valides de CHANGETABLE(). Le client doit confronter la dernière version de synchronisation à la valeur retournée par cette fonction. Si la dernière version de synchronisation est inférieure à la version retournée par cette fonction, le client ne pourra pas obtenir de résultats valides de CHANGETABLE() et devra effectuer une réinitialisation.

Obtenir les données initiales

Pour pouvoir obtenir des modifications pour la première fois, une application doit envoyer une requête afin d'obtenir les données initiales et la version de synchronisation. L'application doit obtenir les données appropriées directement à partir de la table, puis utiliser CHANGE_TRACKING_CURRENT_VERSION() pour obtenir la version initiale. Cette version sera passée à CHANGETABLE (CHANGES ...) la première fois que des modifications seront obtenues.

L'exemple suivant montre comment obtenir la version de synchronisation initiale et le jeu de données initial.

declare @synchronization_version bigint;

-- 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;

Utiliser les fonctions de suivi des modifications pour obtenir les modifications

Pour obtenir les lignes modifiées d’une table et des informations sur les modifications, utilisez CHANGETABLE(CHANGES...). Par exemple, la requête suivante obtient les modifications de la SalesLT.Product table.

declare @last_synchronization_version bigint;

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;

Habituellement, un client souhaite obtenir les données les plus récentes d'une ligne plutôt qu'uniquement les clés primaires de la ligne. Par conséquent, une application doit joindre les résultats de CHANGETABLE(CHANGES ...) aux données de la table utilisateur. Par exemple, la requête suivante établit une jointure avec la table SalesLT.Product afin d'obtenir les valeurs des colonnes Name et ListPrice . Notez l'utilisation de OUTER JOIN. Cela est nécessaire afin de s'assurer que les informations relatives aux modifications sont retournées pour les lignes qui ont été supprimées de la table utilisateur.

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;

Pour obtenir la version à utiliser dans l'énumération de modification suivante, utilisez CHANGE_TRACKING_CURRENT_VERSION(), comme indiqué dans l'exemple suivant.

SET @synchronization_version = CHANGE_TRACKING_CURRENT_VERSION();

Quand une application obtient des modifications, elle doit utiliser à la fois CHANGETABLE(CHANGES ...) et CHANGE_TRACKING_CURRENT_VERSION(), comme indiqué dans l’exemple suivant.

-- 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;

Numéros de version

Une base de données pour laquelle le suivi des modifications est activé possède un compteur de version qui s'incrémente à mesure que des modifications sont apportées afin de modifier des tables faisant l'objet d'un suivi. Chaque ligne modifiée comporte un numéro de version associé. Lorsqu'une demande est envoyée à une application afin de connaître les modifications, une fonction fournissant un numéro de version est appelée. La fonction retourne des informations à propos de toutes les modifications apportées depuis cette version. À certains égards, le concept de version de suivi des modifications est semblable au type de données rowversion .

Valider la dernière version synchronisée

Les informations relatives aux modifications sont maintenues pour une durée limitée. Cette durée est contrôlée par le paramètre CHANGE_RETENTION qui peut être spécifié dans le cadre d'ALTER DATABASE.

L’heure spécifiée pour CHANGE_RETENTION détermine la fréquence à laquelle toutes les applications doivent demander des modifications à partir de la base de données. Si une application a une valeur pour last_synchronization_version antérieure à la version de synchronisation valide minimale d’une table, cette application ne peut pas effectuer d’énumération de modifications valide. Cela est dû au fait que certaines informations de modification ont pu être nettoyées. Avant d’obtenir des modifications à l’aide de CHANGETABLE(CHANGES ...), l’application doit valider la valeur de last_synchronization_version qu’elle envisage de passer à CHANGETABLE(CHANGES ...). Si la valeur de last_synchronization_version n’est pas valide, cette application doit réinitialiser toutes les données.

L'exemple suivant montre vérifier la validité de la valeur de last_synchronization_version pour chaque 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;

Comme l'exemple suivant le montre, la validation de la valeur de last_synchronization_version peut être vérifiée par rapport à toutes les tables de la base de données.

-- Check all tables with change tracking enabled
IF EXISTS (
  SELECT 1 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;

Utiliser le suivi des colonnes

Le suivi de colonne permet aux applications d'obtenir les données relatives uniquement aux colonnes qui ont changé, plutôt que la ligne entière. Par exemple, considérez le scénario dans lequel une table possède une ou plusieurs grandes colonnes qui sont rarement modifiées et d'autres colonnes qui changent fréquemment. Sans le suivi de colonne, une application peut déterminer uniquement qu'une ligne a changé et elle doit synchroniser toutes les données, y compris celles des grandes colonnes. Grâce au suivi de colonne, une application peut déterminer si les données des grandes colonnes ont changé et synchroniser les données uniquement si elles ont changé.

Les informations de suivi de colonne apparaissent dans la colonne SYS_CHANGE_COLUMNS retournée par la fonction CHANGETABLE(CHANGES ...).

Le suivi des colonnes peut être utilisé afin que NULL soit retourné pour une colonne qui n’a pas changé. Si la colonne peut prendre la valeur NULL, une colonne séparée doit être retournée afin d'indiquer si la colonne a changé.

Dans l’exemple suivant, la CT_ThumbnailPhoto colonne sera NULL si cette colonne n’a pas changé. Elle pourrait également être NULL si elle a pris la valeur NULL ; l'application peut utiliser CT_ThumbNailPhoto_Changed afin de déterminer si la colonne a changé.

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';

Obtenir des résultats cohérents et corrects

L'obtention des données modifiées pour une table requiert plusieurs étapes. Des résultats incohérents ou incorrects peuvent être retournés si certains problèmes ne sont pas pris en compte et gérés.

Par exemple, pour obtenir les modifications apportées à une Sales table et SalesOrders une table, une application effectue les étapes suivantes :

  1. Valider la dernière version synchronisée à l'aide de CHANGE_TRACKING_MIN_VALID_VERSION().

  2. Obtenir la version qui peut être utilisée pour obtenir les modifications lors de la prochaine interrogation à l'aide de CHANGE_TRACKING_CURRENT_VERSION().

  3. Obtenez les modifications de la Sales table à l’aide de CHANGETABLE(CHANGES ...).

  4. Obtenez les modifications de la SalesOrders table à l’aide de CHANGETABLE(CHANGES ...).

Deux processus qui se produisent dans la base de données peuvent affecter les résultats retournés par les étapes précédentes :

  • Le processus de nettoyage s'exécute en arrière-plan et supprime les informations de suivi des modifications antérieures à la période de rétention spécifiée.

    Le processus de nettoyage est un processus d'arrière-plan distinct qui utilise la période de rétention spécifiée lorsque vous configurez le suivi des modifications pour la base de données. Le problème réside dans le fait que le processus de nettoyage peut se produire entre la validation de la dernière version de synchronisation et l’appel à CHANGETABLE(CHANGES ...). Une dernière version de synchronisation valide peut ne plus être valide au moment où les modifications sont récupérées. Par conséquent, des résultats incorrects peuvent être retournés.

  • Les opérations DML en cours se produisent dans les tables Sales et SalesOrders les tables, telles que les opérations suivantes :

    • Des modifications peuvent être apportées aux tables après que la version pour la prochaine fois a été obtenue à l'aide de CHANGE_TRACKING_CURRENT_VERSION(). Par conséquent, le nombre de modifications retournées peut être plus important que prévu.

    • Une transaction peut être validée dans le temps entre l’appel pour extraire les modifications de la Sales table et l’appel pour extraire les modifications de la SalesOrders table. Par conséquent, les résultats de la SalesOrder table peuvent avoir une valeur de clé étrangère qui n’existe pas dans la Sales table.

Pour éviter de rencontrer les problèmes mentionnés ci-dessus, nous vous recommandons d'utiliser le niveau d'isolement d'instantané. Cela contribue à garantir la cohérence des informations de modification et à éviter les conditions de concurrence liées à la tâche de nettoyage en arrière-plan. Si vous n’utilisez pas de transactions d’instantané, le développement d’une application qui utilise le suivi des modifications peut nécessiter beaucoup plus d’efforts.

Utiliser l’isolation des instantanés

Le suivi des modifications a été conçu pour une bonne intégration au niveau d'isolement d'instantané. Le niveau d'isolement d'instantané doit être activé pour la base de données. Toutes les étapes requises pour obtenir des modifications doivent être incluses à l'intérieur d'une transaction d'instantané. Cela garantit que toutes les modifications apportées aux données lors de l’obtention des modifications ne seront pas visibles par les requêtes à l’intérieur de la transaction d’instantané.

Pour obtenir des données à l'intérieur d'une transaction d'instantané, procédez comme suit :

  1. Définissez le niveau d'isolation de la transaction à « instantané » et démarrez une transaction.

  2. Validez la dernière version de synchronisation à l'aide de CHANGE_TRACKING_MIN_VALID_VERSION().

  3. Obtenez la version à utiliser lors de la prochaine interrogation à l'aide de CHANGE_TRACKING_CURRENT_VERSION().

  4. Obtenir les modifications de la table à l’aide Sales de CHANGETABLE(CHANGES ...)

  5. Obtenir les modifications de la table à l’aide SalesOrders de CHANGETABLE(CHANGES ...)

  6. Validez la transaction.

Quelques points à noter étant donné que toutes les étapes d'obtention de modifications ont lieu à l'intérieur d'une transaction d'instantané :

  • Si le nettoyage se produit après la validation de la dernière version de synchronisation, les résultats de CHANGETABLE(CHANGES ...) seront toujours valides, car les opérations de suppression effectuées par le nettoyage ne seront pas visibles à l’intérieur de la transaction.

  • Toutes les modifications apportées à la table ou à la SalesSalesOrders table après l’obtention de la prochaine version de synchronisation ne seront pas visibles, et les appels à CHANGETABLE(CHANGES ...) ne retourneront jamais les modifications avec une version ultérieure à celle retournée par CHANGE_TRACKING_CURRENT_VERSION(). La cohérence entre la Sales table et la SalesOrders table sera également conservée, car les transactions validées dans le temps entre les appels à CHANGETABLE(CHANGES ...) ne seront pas visibles.

L'exemple ci-dessous montre comment le niveau d'isolement d'instantané est activé pour une base de données.

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

Une transaction d'instantané est utilisée comme suit :

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

Pour plus d’informations sur les transactions d’instantané, consultez SET TRANSACTION ISOLATION LEVEL (Transact-SQL).

Nettoyage et isolement d’instantané

L’activation de l’isolation des instantanés et du suivi des modifications sur la même base de données, ou sur deux bases de données différentes au sein de la même instance peut entraîner le processus de nettoyage en laissant des lignes expirées sys.syscommittab lorsqu’il existe une transaction ouverte dans la base de données avec isolation d’instantané. Cela peut se produire lorsque le processus de nettoyage du suivi des modifications prend une limite inférieure à l’échelle de l’instance (qui est la version de nettoyage sécurisée) en compte lors de l’exécution du nettoyage. Cela permet de s’assurer que le processus de nettoyage automatique du suivi des modifications ne supprime pas les lignes qui peuvent être requises par la transaction ouverte dans la base de données pour laquelle l’isolation d’instantané est activée. Conservez l’isolation des captures instantanées validées en lecture et les transactions d’isolation des instantanés aussi courtes que possible pour vous assurer que les lignes expirées sont sys.syscommittab nettoyées en temps voulu.

Alternatives à l’isolation des instantanés

Il existe des alternatives à l'utilisation du niveau d'isolement d'instantané, mais elles nécessitent davantage de travail afin de s'assurer que toutes les spécifications d'applications sont satisfaites. Pour vous assurer que la last_synchronization_version est valide et que les données ne sont pas supprimées par le processus de nettoyage avant l’obtention des modifications, procédez comme suit :

  1. Vérifiez last_synchronization_version après les appels à CHANGETABLE().

  2. Vérifiez last_synchronization_version dans le cadre de chaque requête d’obtention de modifications à l’aide de CHANGETABLE().

Des modifications peuvent se produire après l'obtention de la version de synchronisation pour l'énumération suivante. Il existe deux manières de gérer cette situation. L'option utilisée dépend de l'application et de la façon dont elle peut gérer les effets secondaires de chaque approche :

  • Ignorer les modifications dont la version est ultérieure à la nouvelle version de synchronisation.

    Cette approche a comme effet secondaire qu'une ligne nouvelle ou mise à jour est ignorée si elle a été créée ou mise à jour avant la nouvelle version de synchronisation, mais qu'elle a été mise à jour par la suite. S’il existe une nouvelle ligne, un problème d’intégrité référentielle peut se produire s’il y avait une ligne dans une autre table qui a été créée qui a référencé la ligne ignorée. S’il existe une ligne existante mise à jour, la ligne est ignorée et n’est pas synchronisée jusqu’à la prochaine fois.

  • Inclure toutes les modifications, même celles dont la version est ultérieure à la nouvelle version de synchronisation.

    Les lignes qui ont une version ultérieure à la nouvelle version de synchronisation seront encore obtenues lors de la synchronisation suivante. Cela doit être attendu et géré par l'application.

En plus des deux options précédentes, vous pouvez imaginer une approche qui combine ces deux options, selon l'opération. Par exemple, vous souhaiterez peut-être qu’une application pour laquelle il est préférable d’ignorer les modifications plus récentes que la prochaine version de synchronisation dans laquelle la ligne a été créée ou supprimée, mais les mises à jour ne sont pas ignorées.

Note

Le choix de l'approche la mieux adaptée à l'application lorsque vous utilisez le suivi des modifications (ou tout mécanisme de suivi personnalisé) requiert une analyse approfondie. Il est par conséquent beaucoup plus simple d'utiliser le niveau d'isolement d'instantané.

Comment le suivi des modifications gère les modifications apportées à une base de données

Certaines applications qui utilisent le suivi des modifications effectuent une synchronisation bidirectionnelle avec une autre banque de données. Autrement dit, les modifications apportées dans la base de données SQL Server sont mises à jour dans l’autre magasin de données et les modifications apportées dans l’autre magasin sont mises à jour dans la base de données SQL Server.

Lorsqu'une application met à jour la base de données locale avec les modifications d'une autre banque de données, elle doit effectuer les opérations suivantes :

  • Recherche de conflits.

    Un conflit se produit lorsque les mêmes données sont modifiées simultanément dans les deux banques de données. L'application doit être en mesure de vérifier s'il existe un conflit et d'obtenir suffisamment d'informations pour permettre la résolution du conflit.

  • Stockage d'informations de contexte d'application.

    L'application stocke des données qui contiennent les informations de suivi des modifications. Ces informations (ainsi que d'autres informations de suivi des modifications) sont disponibles lorsque les modifications sont obtenues à partir de la base de données locale. Un exemple courant d'information contextuelle de ce type est un identificateur pour la banque de données qui était la source de la modification.

Pour effectuer les opérations précédentes, une application de synchronisation peut utiliser les fonctions suivantes :

  • CHANGETABLE(VERSION...)

    Lorsqu'une application apporte des modifications, elle peut utiliser cette fonction pour vérifier s'il existe des conflits. Cette fonction obtient les informations de suivi des modifications les plus récentes pour une ligne spécifiée dans une table sujette au suivi des modifications. Les informations de suivi des modifications incluent la version de la dernière ligne modifiée. Ces informations permettent à une application de déterminer si la ligne a été modifiée après la dernière synchronisation de l'application.

  • WITH CHANGE_TRACKING_CONTEXT

    Une application peut utiliser cette clause pour stocker des données de contexte.

Rechercher des conflits

Dans un scénario de synchronisation bidirectionnel, l’application cliente doit déterminer si une ligne n’a pas été mise à jour depuis la dernière fois que l’application a obtenu les modifications.

L’exemple suivant montre comment utiliser la fonction CHANGETABLE(VERSION ...) pour vérifier l’existence de conflits de la manière la plus efficace, sans requête distincte. Dans l'exemple, CHANGETABLE(VERSION ...) détermine SYS_CHANGE_VERSION pour la ligne spécifiée par @product id. CHANGETABLE(CHANGES ...) peut obtenir les mêmes informations, mais il est moins efficace. Si la valeur de SYS_CHANGE_VERSION la ligne est supérieure à la valeur de @last_sync_version, il existe un conflit. En cas de conflit, la ligne n’est pas mise à jour. Le contrôle ISNULL() est nécessaire car il se peut qu'il n'y ait aucune information de modification disponible pour la ligne. Aucune information de modification n’existe si la ligne n’avait pas été mise à jour depuis l’activation du suivi des modifications ou depuis le nettoyage des informations de modification.

-- 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);

Le code suivant peut vérifier le nombre de lignes mises à jour et identifier davantage d'informations relatives au conflit.

-- 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

Définir des informations de contexte

Avec la clause WITH CHANGE_TRACKING_CONTEXT, une application peut stocker des informations de contexte avec les informations de modifications. Ces informations peuvent ensuite être obtenues à partir de la colonne SYS_CHANGE_CONTEXT retournée par CHANGETABLE(CHANGES ...).

Les informations de contexte sont utilisées en général pour identifier la source des modifications. Si la source de la modification peut être identifiée, ces informations peuvent être utilisées par une banque de données afin d'éviter d'obtenir les modifications lors de la synchronisation suivante.

-- 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);

Garantir des résultats cohérents et corrects

Une application doit prendre en compte le processus de nettoyage lorsqu’elle valide la valeur de @last_sync_version. car des données peuvent avoir été supprimées après l'appel à CHANGE_TRACKING_MIN_VALID_VERSION() mais avant la mise à jour.

Vous devez utiliser l’isolation des instantanés et apporter les modifications dans une transaction d’instantané.

-- 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;

Note

Il est possible que la ligne mise à jour dans le cadre de la transaction d'instantané ait été mise à jour dans une autre transaction après le démarrage de la transaction d'instantané. Dans ce cas, un conflit de mise à jour du niveau d'isolement d'instantané se produit et provoque la fin de la transaction. Si cela se produit, réessayez d'effectuer la mise à jour. Cette tentative génère alors la détection d'un conflit de suivi des modifications et aucune ligne n'est modifiée.

Suivi des modifications et restauration des données

Les applications qui nécessitent une synchronisation doivent considérer le cas où une base de données pour laquelle le suivi des modifications est activé rétablit une version antérieure des données. Cela peut se produire après la restauration d’une base de données à partir d’une sauvegarde, en cas de basculement vers un miroir de bases de données asynchrone ou en cas de défaillance lors de l’utilisation de la copie des journaux de transaction. Le scénario suivant illustre ce problème :

  1. Le tableau T1 est suivi des modifications et la version minimale valide de la table est 50.

  2. Une application cliente synchronise les données à la version 100 et obtient des informations sur toutes les modifications entre les versions 50 et 100.

  3. Des modifications supplémentaires sont apportées à la table T1 après la version 100.

  4. À la version 120, l’administrateur de la base de données restaure la base de données avec une perte de données. Après l'opération de restauration, la table contient des données allant jusqu'à la version 70 et la version synchronisée minimale reste encore 50.

    Cela signifie que la banque de données synchronisée comporte des données qui n'existent plus dans la banque de données primaire.

  5. T1 est mise à jour de nombreuses fois, ce qui porte la version actuelle à 130.

  6. L'application cliente se synchronise de nouveau et fournit une dernière version synchronisée de 100. Le client valide ce numéro avec succès parce que 100 est supérieur à 50.

    Le client obtient les modifications entre les versions 100 et 130. À ce stade, le client ne sait pas que les modifications comprises entre 70 et 100 ne sont pas les mêmes qu’auparavant. Les données sur le client et le serveur ne sont pas synchronisées.

Si la base de données a été récupérée à un point après la version 100, il n’y aurait aucun problème avec la synchronisation. Le client et le serveur synchroniseraient correctement les données pendant l'intervalle de synchronisation suivant.

Le suivi des modifications ne prend pas en charge la récupération à partir de la perte de données. Toutefois, il existe deux possibilités pour détecter ces types de problèmes de synchronisation :

  • Stockez un ID de version de la base de données sur le serveur, puis mettez à jour cette valeur chaque fois qu'une base de données est récupérée ou perd des données. Chaque application cliente stocke l'ID et chaque client doit valider cet ID lorsqu'il synchronise des données. Si la perte de données se produit, les ID ne correspondent pas et les clients réinitialisent. L’un des inconvénients est que la perte de données n’avait pas franchi la dernière limite synchronisée, le client peut effectuer une réinitialisation inutile.

  • Lorsqu'un client interroge les modifications, enregistrez le numéro de version de la dernière synchronisation pour chaque client sur le serveur. En cas de problème avec les données, les derniers numéros de version synchronisés ne correspondent pas. Ils indiquent qu'une réinitialisation est requise.

Voir aussi