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 à la base de données SQL Server sont mises à jour dans l'autre banque de données et les modifications apportées à l'autre banque 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.
Recherche de conflits
Dans un scénario de synchronisation bidirectionnelle, l'application cliente doit déterminer si une ligne n'a pas été mise à jour depuis la dernière obtention des 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 l'objet SYS_CHANGE_VERSION pour la ligne spécifiée par @product id. CHANGETABLE(CHANGES …) peut obtenir les mêmes informations, mais avec une efficacité moindre. Si la valeur de SYS_CHANGE_VERSION pour la ligne est supérieure à la valeur de @last\_sync\_version, il existe un conflit. En cas de conflit, la ligne ne sera 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'a 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éfinition 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)
Garantie de 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.
Important
Nous vous recommandons d'utiliser le niveau d'isolement de capture instantanée et d'effectuer les modifications dans une transaction de capture instantanée.
-- 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
[!REMARQUE]
Il est possible que la ligne mise à jour dans le cadre de la transaction de capture instantanée ait été mise à jour dans une autre transaction après le démarrage de la transaction de capture instantanée. Dans ce cas, un conflit de mise à jour du niveau d'isolement de capture instantanée 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.