SqlServer 變更追蹤(Chang Tracking),sqlservertracking

來源:互聯網
上載者:User

SqlServer 變更追蹤(Chang Tracking),sqlservertracking


對於追蹤資料庫表的 DML 操作,SQLserver 2008 及以上版本提供了 變更資料擷取和變更追蹤。


變更資料庫捕獲 與 跟蹤更改 的區別:

變更資料擷取與變更追蹤都是記錄表的DML操作

變更資料擷取可把操作資料的曆史值儲存下來;變更追蹤捕獲更改了表行這一事實,但不會捕獲更改的資料。

變更資料擷取使用非同步進程捕獲,該進程掃描交易記錄;變更追蹤同步跟蹤DML操作

變更資料擷取儲存在當前資料庫system表中,更改表可指定儲存位置;變更追蹤表格儲存體在系統架構sys中,不可查看結構定義

更多參考:比較變更資料擷取和變更追蹤



【接下來測試】


建立測試表:

USE [MyDatabase]GOCREATE TABLE [dbo].[TestTab]([id] [int] NOT NULL,[name] [varchar](50) NOT NULL,[insertDate] [datetime] NOT NULL,[value] [numeric](14, 4) NULL,[info] [varchar](20) NULL,CONSTRAINT [PK_TestTab] PRIMARY KEY CLUSTERED ([id] ASC)ON [PRIMARY]) ON [PRIMARY]GO

啟用資料庫變更追蹤:(參考:ALTER DATABASE SET 選項 (Transact-SQL))

USE [master]GOALTER DATABASE [MyDatabase] SET CHANGE_TRACKING = ON (CHANGE_RETENTION = 2 DAYS,AUTO_CLEANUP = ON)GO



啟用表的變更追蹤:(參考:ALTER TABLE (Transact-SQL))

USE [MyDatabase]GOALTER TABLE [dbo].[TestTab] ENABLE CHANGE_TRACKING WITH(TRACK_COLUMNS_UPDATED = ON)GO


查看資料庫或表啟用情況:(參考:sys.change_tracking_databases,sys.change_tracking_tables)

SELECT DB_NAME(database_id) DBName,retention_period,retention_period_units_desc,is_auto_cleanup_onFROM sys.change_tracking_databases SELECT OBJECT_NAME(object_id) TableName,is_track_columns_updated_onFROM sys.change_tracking_tables


那跟蹤表的資料存放區在哪呢?使用內部表可查看

-- 每個啟用跟蹤的表儲存一行SELECT * FROM sys.internal_tables WHERE internal_type_desc='CHANGE_TRACKING'SELECT * FROM sys.sysobjects WHERE id = (SELECT object_id FROM sys.internal_tables WHERE internal_type_desc='CHANGE_TRACKING'AND parent_object_id=object_id('TestTab'))--查看錶大小exec sp_spaceused 'sys.change_tracking_37575172'exec sp_spaceused 'sys.syscommittab'


插入測試資料:

--插入測試資料insert into [dbo].[TestTab](id,name,insertDate,value,info)select 1,'kk',GETDATE(),10,'info'union allselect 2,'GG',GETDATE(),50,''union allselect 3,'MM',GETDATE(),0,null

怎麼查看跟蹤資訊,系統提供了一個表值函數 CHANGETABLE :

--返回<版本號碼>之後的所有行更改資訊(如:查看版本號碼為0及之後的所有更改資訊)--SELECT * FROM CHANGETABLE(CHANGES <表名>,<版本號碼>) as TSELECT * FROM CHANGETABLE(CHANGES dbo.TestTab,0) as T--返回指定行的最新變更追蹤資訊(如: id=3 最新更改情況)--SELECT * FROM CHANGETABLE(VERSION <表名>,(<主鍵列>),(<主索引值>)) as TSELECT * FROM CHANGETABLE(VERSION dbo.TestTab,(id),(3)) as T


CHANGETABLE CHANGES:

列名

資料類型

說明

SYS_CHANGE_VERSION

bigint

與上次對行的更改關聯的版本值。(同一批次操作,版本號碼相同)

SYS_CHANGE_CREATION_VERSION

bigint

與上次插入操作關聯的版本值。(同一批次操作,版本號碼相同)

SYS_CHANGE_OPERATION

nchar(1)

指定更改的類型:

U = 更新

I = 插入

D = 刪除

SYS_CHANGE_COLUMNS

varbinary(4100)

列出自基準版本以後發生了更改的列。

 [注意]

計算資料行永遠不會作為更改的列列出。

以下任何一個條件為真時,值為 NULL:

*未啟用列變更追蹤。

*操作是插入操作或刪除操作。

*在一個操作中更新了所有非主鍵列。不應直接解釋此二進位值。

SYS_CHANGE_CONTEXT

varbinary(128)

更改可以在 INSERT、UPDATE 或 DELETE 語句中使用 WITH 子句選擇指定的上下文資訊。

<<主鍵列值>>

與使用者表列相同

被跟蹤表的主鍵值。這些值在使用者表中唯一標識各行。(與當前表串連反應最新資料)


CHANGETABLE VERSION :

列名                

資料類型           

說明

SYS_CHANGE_VERSION

bigint

與行關聯的當前更改版本值。

如果在超過變更追蹤保留期的時段內沒有變更,或者在啟用變更追蹤之後未更改行,則值為 NULL。

SYS_CHANGE_CONTEXT

varbinary(128)

更改可以在 INSERT、UPDATE 或 DELETE 語句中使用 WITH 子句選擇指定的上下文資訊。

<<主鍵列值>>

與使用者表列相同

被跟蹤表的主鍵值。這些值在使用者表中唯一標識各行。(與當前表串連反應最新資料)


更改資料:

update [dbo].[TestTab] set insertDate = GETDATE(),info = 'update' where id=3update [dbo].[TestTab] set insertDate = GETDATE(),value = 100 where id=3 --執行了2次

檢查版本號碼資訊:(參考:CHANGE_TRACKING_MIN_VALID_VERSION,CHANGE_TRACKING_CURRENT_VERSION)

--擷取一個表的最低有效版本號碼SELECT CHANGE_TRACKING_MIN_VALID_VERSION( OBJECT_ID('dbo.TestTab'))--返回與上次提交的事務相關聯的版本,以確定下次需要更改時將使用的版本SELECT CHANGE_TRACKING_CURRENT_VERSION()
--------------------0(1 行受影響)--------------------4(1 行受影響)

再次用CHANGETABLE 查看:

SELECT * FROM CHANGETABLE(CHANGES dbo.TestTab,0) as T

為什麼不是更新(SYS_CHANGE_OPERATION = 'U')??

last_sync_version = 0 為當時的跟蹤情況,現在 SYS_CHANGE_VERSION 已經大於1 了,要查詢各狀態當時更改情況,如:

--返回最後一次版本號碼之後的更改(需指定 last_sync_version )--該值 last_sync_version 必須保持記住,下次可以現在查到的@last_sync_version = CHANGE_TRACKING_CURRENT_VERSION()SELECT * FROM CHANGETABLE(CHANGES dbo.TestTab,0) as TSELECT * FROM CHANGETABLE(CHANGES dbo.TestTab,1) as TSELECT * FROM CHANGETABLE(CHANGES dbo.TestTab,2) as TSELECT * FROM CHANGETABLE(CHANGES dbo.TestTab,3) as T

註:最後兩次更改是相同的的,所以 SYS_CHANGE_COLUMNS 一樣。


還可以使用 CHANGE_TRACKING_IS_COLUMN_IN_MASK查看更改列情況 (需啟用 TRACK_COLUMNS_UPDATED = ON )

--檢查變更追蹤(查看哪些列曾更改)SELECT CHANGE_TRACKING_IS_COLUMN_IN_MASK (<column_id>,<change_columns>)--column_id : 是正在被檢查的列的 ID。 可以使用 COLUMNPROPERTY 函數擷取此列 ID。--change_columns : 是 CHANGETABLE 資料的 SYS_CHANGE_COLUMNS 列中的位元據。--(如主鍵列更改,視為刪除舊值,插入新值)SELECT id,CHANGE_TRACKING_IS_COLUMN_IN_MASK(COLUMNPROPERTY(OBJECT_ID('TestTab'),'id','COLUMNID'),SYS_CHANGE_COLUMNS) id_is_changed,CHANGE_TRACKING_IS_COLUMN_IN_MASK(COLUMNPROPERTY(OBJECT_ID('TestTab'),'name','COLUMNID'),SYS_CHANGE_COLUMNS) name_is_changed,CHANGE_TRACKING_IS_COLUMN_IN_MASK(COLUMNPROPERTY(OBJECT_ID('TestTab'),'insertDate','COLUMNID'),SYS_CHANGE_COLUMNS) insertdate_is_changed,CHANGE_TRACKING_IS_COLUMN_IN_MASK(COLUMNPROPERTY(OBJECT_ID('TestTab'),'value','COLUMNID'),SYS_CHANGE_COLUMNS) value_is_changed,CHANGE_TRACKING_IS_COLUMN_IN_MASK(COLUMNPROPERTY(OBJECT_ID('TestTab'),'info','COLUMNID'),SYS_CHANGE_COLUMNS) info_is_changedFROM CHANGETABLE(CHANGES dbo.TestTab,1) AS TWHERE SYS_CHANGE_OPERATION='U'


在進行刪除和插入操作:

delete from [dbo].[TestTab] where id=1insert into [dbo].[TestTab](id,name,insertDate,value,info)select 4,'kk',GETDATE(),10,'info'

--查看版本號碼為3之後都操作了什麼?SELECT * FROM CHANGETABLE(CHANGES dbo.TestTab,3) as T


對於當前表的記錄是:

SELECT T.id,SYS_CHANGE_OPERATION,SYS_CHANGE_VERSION,D.*FROM CHANGETABLE(CHANGES dbo.TestTab,3) AS TLEFT JOIN [dbo].[TestTab] AS D ON T.id = D.id


對於資料定時轉移的情況:源表中資料進行了 insert,update,delete 操作目標表操作如下:insert : 跟蹤表關聯源表,查詢到的資料插入到目標表中.(即使插入後的資料發送更改,在改版本號碼之顯示還是操作插入"I")update : 跟蹤表關聯源表,查詢到的資料更新到目標表中.也可使用函數 CHANGE_TRACKING_IS_COLUMN_IN_MASK 更新了哪些列delete : 對於刪除 (SYS_CHANGE_OPERATION = 'D'),跟蹤表直接對目標表進行刪除(注意主鍵不可相同!否則可能刪錯)

--資料轉移情況,根據版本號碼更改,所以版本號碼要記住!源表: [TestTab]目標表: [TargetTestTab]--insert : INSERT INTO [TargetTestTab](id,name,insertDate,value,info)SELECT D.id,name,insertDate,value,infoFROM CHANGETABLE(CHANGES dbo.TestTab,3) AS TINNER JOIN [dbo].[TestTab] AS D ON T.id = D.idWHERE SYS_CHANGE_OPERATION = 'I'--update : UPDATE K SET K.id=D.id,K.name=D.name,K.insertDate=D.insertDate,K.value=D.value,K.info=D.infoFROM CHANGETABLE(CHANGES dbo.TestTab,3) AS TINNER JOIN [dbo].[TestTab] AS D ON T.id = D.idINNER JOIN [dbo].[TargetTestTab] K ON D.id=K.idWHERE SYS_CHANGE_OPERATION = 'U'--delete : DELETE FROM [dbo].[TargetTestTab] WHERE id IN(SELECT id FROM CHANGETABLE(CHANGES dbo.TestTab,3) AS TWHERE SYS_CHANGE_OPERATION = 'D')

轉移資料前,先查看當前的版本號碼 CHANGE_TRACKING_CURRENT_VERSION()  ,例如500 。而上面的操作中,版本號碼為3,這批資料相應更改完成後,下次從版本號碼500開始。當然可能有誤差,因為在操作這批資料時,當前可能有其他動作,版本號碼也在累計。

建議使用快照隔離等級,保證事務的一致性:

ALTER DATABASE [MyDatabase] SET ALLOW_SNAPSHOT_ISOLATION ON;

最後禁用變更追蹤:

--對錶禁用ALTER TABLE [dbo].[TestTab] DISABLE CHANGE_TRACKING GO--對資料庫禁用ALTER DATABASE [MyDatabase] SET CHANGE_TRACKING = OFF GO


參考:

變更追蹤概述

變更追蹤

使用變更追蹤函數擷取更改


相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.