Utiliser le change tracking pour la synchronisation des données
Par Arian Papillon le lundi 4 juillet 2011, 17:44 - Lien permanent
Le change tracking (suivi des modifications) est une des fonctionnalités apparues avec SQL Server 2008. Cette fonctionnalité est très pratique lorsqu'il s'agit d'identifier les données qui ont été ajoutées, modifiées ou supprimées, pour en faire périodiquement la mise à jour dans une autre table dont les données doivent rester synchronisées. L'enregistrement ajouté, mis à jour ou supprimé dans l'intervalle sera facile à localiser à travers des vues système : auparavant, nous aurions écrit un trigger et une table de journalisation pour faire ce travail...!
Une fonctionnalité à ne pas confondre avec le CDC (Change Data Capture ou capture des données modifiées), qui capture toutes les modifications effectuées grâce à une tâche de log reader (version entreprise uniquement).
Un exemple de change tracking pour synchroniser en mode planifié les données entre deux tables.
-- Création d'une base et d'une table source USE master GO CREATE DATABASE ChangeTrackingSource go USE ChangeTrackingSource SELECT [BusinessEntityID] , [PersonType] , [FirstName] , [LastName] INTO person FROM AdventureWorks2008R2.Person.Person go ALTER TABLE person ADD CONSTRAINT pk_person PRIMARY KEY CLUSTERED ( BusinessEntityID ) -- Une PK est nécessaire pour le change tracking go -- Création d'une base et table destination USE master go CREATE DATABASE ChangeTrackingTarget go USE ChangeTrackingTarget Go CREATE TABLE [SynchroPerson] ( [BusinessEntityID] [int] NOT NULL , [PersonType] [nchar](2) NULL , [FirstName] NVARCHAR(50) NULL , [LastName] NVARCHAR(50) NULL , CONSTRAINT [PK_Person_BusinessEntityID] PRIMARY KEY CLUSTERED ( [BusinessEntityID] ASC ) ) GO INSERT SynchroPerson SELECT * FROM ChangeTrackingSource..person -- mêmes données GO -- Je crée aussi une table pour conserver les versions de la source pour le change tracking CREATE TABLE CT_SourceVersion ( CT_version BIGINT ) INSERT CT_SourceVersion DEFAULT VALUES GO -- Activation du change tracking pour la base et pour la table source USE master GO ALTER DATABASE ChangeTrackingSource SET CHANGE_TRACKING= ON ( CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON ) GO USE ChangeTrackingSource GO ALTER TABLE person ENABLE CHANGE_TRACKING WITH ( TRACK_COLUMNS_UPDATED = ON) GO -- initialisation du change tracking, mes tables sont synchrones et je stocke la version actuelle UPDATE ChangeTrackingTarget..CT_SourceVersion SET CT_Version = ( SELECT CHANGE_TRACKING_CURRENT_VERSION() ) -- faire quelques mises à jour, ajouts et suppressions successifs dans ma source UPDATE Person SET FirstName = 'paul' , LastName = 'allen' WHERE BusinessEntityID = 1 go UPDATE Person SET FirstName = 'bill' , LastName = 'gates' WHERE BusinessEntityID = 1 go INSERT Person ( BusinessEntityID , PersonType , FirstName , LastName ) VALUES ( 310 , 'SC' , 'Joan' , 'Ballmer' ) go UPDATE Person SET FirstName = 'steve' WHERE BusinessEntityID = 310 GO DELETE person WHERE BusinessEntityID = 2 GO ----------- Le change tracking, je vais synchroniser mes tables ---- SELECT * FROM ChangeTrackingTarget..SynchroPerson WHERE BusinessEntityID IN ( 1, 2, 310 ) -- juste pour montrer que les modification ne sont pas dans ma cible DECLARE @sync_version BIGINT SELECT @sync_version = CT_version FROM ChangeTrackingTarget..CT_SourceVersion -- je récupère la version -- et j'affiche les modifications de ma source depuis cette version SELECT CT.BusinessEntityID , p.persontype , p.firstname , p.lastname , CT.SYS_CHANGE_OPERATION , CT.SYS_CHANGE_COLUMNS , CT.SYS_CHANGE_CONTEXT FROM CHANGETABLE(CHANGES Person, @sync_version) CT LEFT JOIN Person p ON CT.BusinessEntityID = p.BusinessEntityID -- Je peux donc synchroniser : INSERT, UPDATE, DELETE DECLARE @sync_version BIGINT SELECT @sync_version = CT_version FROM ChangeTrackingTarget..CT_SourceVersion INSERT ChangeTrackingTarget..SynchroPerson ( BusinessEntityID , PersonType , FirstName , LastName ) SELECT CT.BusinessEntityID , p.persontype , p.firstname , p.lastname FROM CHANGETABLE(CHANGES Person, @sync_version) CT JOIN Person p ON CT.BusinessEntityID = p.BusinessEntityID AND CT.SYS_CHANGE_OPERATION = 'I' UPDATE ChangeTrackingTarget..SynchroPerson SET FirstName = p.Firstname , LastName = p.Lastname , PersonType = p.Persontype FROM ChangeTrackingTarget..SynchroPerson JOIN CHANGETABLE(CHANGES Person, @sync_version) CT ON ChangeTrackingTarget..SynchroPerson.BusinessEntityID = CT.BusinessEntityID AND CT.SYS_CHANGE_OPERATION = 'U' JOIN Person p ON CT.BusinessEntityID = p.BusinessEntityID DELETE ChangeTrackingTarget..SynchroPerson WHERE BusinessEntityID in ( SELECT CT.BusinessEntityID FROM CHANGETABLE(CHANGES Person, @sync_version) CT WHERE CT.SYS_CHANGE_OPERATION = 'D' ) -- Vérifions SELECT * FROM ChangeTrackingTarget..SynchroPerson WHERE BusinessEntityID IN ( 1, 2, 310 ) -- si tout s'est bien passé, je conserve le nouveau numéro de version pour la prochaine fois UPDATE ChangeTrackingTarget..CT_SourceVersion SET CT_Version = ( SELECT CHANGE_TRACKING_CURRENT_VERSION() )