一.本文所涉及的內容(Contents)
二.背景(Contexts)
在SQL Server 2008以上版本中,對數據庫中的用戶表所做的 DML 更改(插入、更新和刪除操作)除了:SQL Server 變更數據捕獲(CDC)監控表數據之外,還有一個新增功能,那就是:更改跟蹤(Chang Tracking),它跟CDC有什么不同呢?使用場景有什么區別呢?
三.主要區別與對比(Compare)
1. SQL Server 2008 引入了兩項跟蹤功能:變更數據捕獲和更改跟蹤,以使應用程序能夠確定對數據庫中的用戶表所做的 DML 更改(插入、更新和刪除操作);
2. 如果應用程序需要有關所有所做更改的信息以及所更改數據的中間值,則可能適合使用變更數據捕獲,而不適合使用更改跟蹤。有關詳細信息,請參閱比較變更數據捕獲和更改跟蹤和變更數據捕獲。
3. 變更數據捕獲使用異步進程捕獲,此進程讀取事務日志;更改跟蹤是與DML操作同步的,不需要讀取事務日志;
4. 變更數據捕獲包含了變更的歷史記錄,更改跟蹤只保存行,但不會捕獲更改的數據;
更改跟蹤可以根據外部傳入的應用程序上下文,來完成更細顆粒度的更改處理,參考:WITH CHANGE_TRACKING_CONTEXT
四.實現監控表數據步驟(Process)
/******* Step1:創建示例數據庫*******/ USE MASTER GO IF EXISTS(SELECT name FROM sys.databases WHERE name = 'CT_DB') DROP DATABASE CT_DB GO CREATE DATABASE CT_DB GO
(二) 開啟數據庫更改跟蹤Chang Tracking,通過下面的SQL腳本可以查詢開啟了更改跟蹤的數據庫列表;
/******* Step2:開啟數據庫更改跟蹤Chang Tracking *******/ --啟用更改跟蹤(Chang Tracking),天清理一次(HOURS) ALTER DATABASE CT_DB SET CHANGE_TRACKING = ON (CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON) --查看數據庫是否啟用更改跟蹤 SELECT DB_NAME(database_id) DataBaseName,is_auto_cleanup_on, retention_period,retention_period_units_desc FROM sys.change_tracking_databases
(Figure1:查看數據庫是否啟用更改跟蹤)
(三) 開啟數據庫更改跟蹤Chang Tracking,通過下面的SQL腳本可以查詢開啟了更改跟蹤的數據庫列表;
/******* Step3:對表啟用更改跟蹤*******/ --創建測試表 USE CT_DB GO CREATE TABLE [dbo].[Department]( [DepartmentID] [smallint] IDENTITY(1,1) NOT NULL, [Name] [nvarchar](200) NULL, [GroupName] [nvarchar](50) NOT NULL, [ModifiedDate] [datetime] NOT NULL, [AddName] [nvarchar](120) NULL, CONSTRAINT [PK_Department_DepartmentID] PRIMARY KEY CLUSTERED ( [DepartmentID] ASC ) ON [PRIMARY] ) ON [PRIMARY] GO --對表啟用更改跟蹤 ALTER TABLE [dbo].[Department] ENABLE CHANGE_TRACKING WITH (TRACK_COLUMNS_UPDATED = ON) --查看表是否啟用更改跟蹤 SELECT OBJECT_NAME(object_id) TableName,is_track_columns_updated_on FROM sys.change_tracking_tables
(Figure2:查看表是否啟用更改跟蹤)
(四) 測試對Department表進行DML操作:分兩次把數據插入到表,並使用下面的SQL腳本查看變更跟蹤信息,從中可以發現,兩次不同的插入會生成兩個版本,這可以證明變更跟蹤是跟DML操作是同步的;
/******* Step4:測試DML變更跟蹤*******/ --測試插入數據(版本將變成1) INSERT INTO dbo.Department( Name , GroupName , ModifiedDate )VALUES('Marketing','Sales and Marketing',GETDATE()) --再次測試插入數據(版本將變成2) INSERT INTO dbo.Department( Name , GroupName , ModifiedDate )VALUES ('Production','Manufacturing',GETDATE()), ('Purchasing','Inventory Management',GETDATE()) --表記錄 SELECT * FROM dbo.Department --當前版本 SELECT CHANGE_TRACKING_CURRENT_VERSION () AS CURRENT_VERSION --最小版本 SELECT CHANGE_TRACKING_MIN_VALID_VERSION (OBJECT_ID('dbo.Department')) AS MIN_VERSION --使用Changes關鍵字查看更改信息 SELECT DepartmentID,SYS_CHANGE_OPERATION,SYS_CHANGE_VERSION FROM CHANGETABLE(CHANGES dbo.Department, 0) AS CT
(Figure3:更改跟蹤信息)
(五) 繼續測試對Department表進行DML操作:做一次Update操作、做一次Delete操作;
--測試更新數據(版本將變成3) UPDATE dbo.Department SET Name = 'Marketing Group',ModifiedDate = GETDATE() WHERE Name = 'Marketing' --測試刪除數據(版本將變成4) DELETE FROM dbo.Department WHERE Name='Production' --表記錄 SELECT * FROM dbo.Department --當前版本 SELECT CHANGE_TRACKING_CURRENT_VERSION () AS CURRENT_VERSION --最小版本 SELECT CHANGE_TRACKING_MIN_VALID_VERSION (OBJECT_ID('dbo.Department')) AS MIN_VERSION --查看版本2之后的更改 SELECT DepartmentID,SYS_CHANGE_OPERATION,SYS_CHANGE_VERSION,SYS_CHANGE_COLUMNS FROM CHANGETABLE(CHANGES dbo.Department, 2) AS CT
(Figure4:更改跟蹤信息)
(六) 查看列變更說明;
--返回哪些列被修改,1為真,0為假 SELECT DepartmentID, CHANGE_TRACKING_IS_COLUMN_IN_MASK( COLUMNPROPERTY( OBJECT_ID('dbo.Department'),'Name', 'ColumnId') , SYS_CHANGE_COLUMNS) '是否改變Name', CHANGE_TRACKING_IS_COLUMN_IN_MASK( COLUMNPROPERTY( OBJECT_ID('dbo.Department'),'GroupName', 'ColumnId') , SYS_CHANGE_COLUMNS) '是否改變GroupName', CHANGE_TRACKING_IS_COLUMN_IN_MASK( COLUMNPROPERTY( OBJECT_ID('dbo.Department'), 'ModifiedDate', 'ColumnId') , SYS_CHANGE_COLUMNS) '是否改變ModifiedDate' FROM CHANGETABLE(CHANGES dbo.Department, 2) AS CT WHERE SYS_CHANGE_OPERATION = 'U'
(Figure5:列變更說明)
(七) 使用Version關鍵字查看更改信息;
--使用Version關鍵字查看更改信息 SELECT * FROM dbo.Department d CROSS APPLY CHANGETABLE(VERSION dbo.Department, (DepartmentID), (d.DepartmentID)) AS ct
(Figure6:Version關鍵字查看更改信息)
(八) 通過在外部應用程序中的上下文信息判斷這個DML是由哪個應用產生的;
--設置跟蹤外部程序上下文信息 DECLARE @context VARBINARY(128) = CAST('我要插入記錄' AS VARBINARY(128)); WITH CHANGE_TRACKING_CONTEXT (@context) --測試插入數據(版本將變成) INSERT INTO dbo.Department( Name , GroupName , ModifiedDate )VALUES('Document Control','Quality Assurance',GETDATE()) --查詢Context更改 SELECT DepartmentID,SYS_CHANGE_OPERATION,SYS_CHANGE_VERSION, CAST(SYS_CHANGE_CONTEXT AS VARCHAR) ApplicationContext FROM CHANGETABLE(CHANGES dbo.Department, 4) AS CT
(Figure7:上下文信息)
(九) 獲取更改跟蹤版本2之后的表數據;
--獲取更改跟蹤版本2之后的表數據 SELECT SYS_CHANGE_OPERATION,SYS_CHANGE_VERSION,SYS_CHANGE_COLUMNS,D.* FROM CHANGETABLE(CHANGES dbo.Department, 2) AS CT LEFT JOIN dbo.Department AS D ON CT.DepartmentID = D.DepartmentID
(Figure8:更改表記錄)
(十) 總結:在更改跟蹤的記錄中包括了表Department 的唯一編號,還有DML的操作符字段SYS_CHANGE_OPERATION,枚舉這些值(I=Insert、U=Update、D=Delete),還有DML操作的版本號:SYS_CHANGE_VERSION,它是每進行一次DML,都會遞增一個版本號,所以你可以針對I=Insert、U=Update、D=Delete不同的類型加上版本號過濾,就可以找到那些數據進行了更新;