对于跟踪数据库表的 DML 操作,SQLserver 2008 及以上版本提供了 变更数据捕获和更改跟踪。

变更数据库捕获 与 跟踪更改 的区别:

变更数据捕获与更改跟踪都是记录表的DML操作

变更数据捕获可把操作数据的历史值保存下来;更改跟踪捕获更改了表行这一事实,但不会捕获更改的数据。

变更数据捕获使用异步进程捕获,该进程扫描事务日志;更改跟踪同步跟踪DML操作

变更数据捕获存储在当前数据库system表中,更改表可指定存储位置;更改跟踪表存储在系统架构sys中,不可查看结构定义

更多参考: 比较变更数据捕获和更改跟踪

【接下来测试】


创建测试表:

USE [MyDatabase]
GO
CREATE 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]
GO
ALTER DATABASE [MyDatabase] SET CHANGE_TRACKING = ON (CHANGE_RETENTION = 2 DAYS,AUTO_CLEANUP = ON)
GO

启用表的更改跟踪:(参考:ALTER TABLE (Transact-SQL))

USE [MyDatabase]
GO
ALTER 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_on
FROM sys.change_tracking_databasesSELECT OBJECT_NAME(object_id) TableName,is_track_columns_updated_on
FROM 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 all
select 2,'GG',GETDATE(),50,''
union all
select 3,'MM',GETDATE(),0,null

怎么查看跟踪信息,系统提供了一个表值函数 CHANGETABLE :

--   返回<版本号>之后的所有行更改信息(如:查看版本号为0及之后的所有更改信息)
--  SELECT * FROM CHANGETABLE(CHANGES <表名>,<版本号>) as T
SELECT * FROM CHANGETABLE(CHANGES dbo.TestTab,0) as T-- 返回指定行的最新更改跟踪信息(如: id=3 最新更改情况)
--  SELECT * FROM CHANGETABLE(VERSION <表名>,(<主键列>),(<主键值>)) as T
SELECT * 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=3
update [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 行受影响)
--或者
SELECT min_valid_version,begin_version
FROM sys.change_tracking_tables WHERE OBJECT_NAME(object_id) = 'TestTab'select MAX(commit_ts) from sys.dm_tran_commit_table

再次用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 T
SELECT * FROM CHANGETABLE(CHANGES dbo.TestTab,1) as T
SELECT * FROM CHANGETABLE(CHANGES dbo.TestTab,2) as T
SELECT * 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_changed
FROM CHANGETABLE(CHANGES dbo.TestTab,1) AS T
WHERE 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 T
LEFT 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,info
FROM CHANGETABLE(CHANGES dbo.TestTab,3) AS T
INNER JOIN [dbo].[TestTab] AS D ON T.id = D.id
WHERE 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.info
FROM CHANGETABLE(CHANGES dbo.TestTab,3) AS T
INNER JOIN [dbo].[TestTab] AS D ON T.id = D.id
INNER JOIN [dbo].[TargetTestTab] K ON D.id=K.id
WHERE 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

附件:

--查看跟踪表大小select sct1.name as CT_schema,sot1.name as CT_table,ps1.row_count as CT_rows,ps1.reserved_page_count*8./1024. as CT_reserved_MB,sct2.name as tracked_schema,sot2.name as tracked_name,ps2.row_count as tracked_rows,ps2.reserved_page_count*8./1024. as tracked_base_table_MB,change_tracking_min_valid_version(sot2.object_id) as min_valid_version
FROM sys.internal_tables it
JOIN sys.objects sot1 on it.object_id=sot1.object_id
JOIN sys.schemas AS sct1 on sot1.schema_id=sct1.schema_id
JOIN sys.dm_db_partition_stats ps1 on it.object_id = ps1. object_id and ps1.index_id in (0,1)
LEFT JOIN sys.objects sot2 on it.parent_object_id=sot2.object_id
LEFT JOIN sys.schemas AS sct2 on sot2.schema_id=sct2.schema_id
LEFT JOIN sys.dm_db_partition_stats ps2 on sot2.object_id = ps2. object_id and ps2.index_id in (0,1)
WHERE it.internal_type IN (209, 210);
GO

参考:

更改跟踪概述

更改跟踪

使用更改跟踪函数获取更改

SqlServer 更改跟踪(Chang Tracking)相关推荐

  1. SQL Server 变更数据捕获(CDC)vs 更改跟踪(Chang Tracking)

    一. CDC简介 在2008版本之前,通常使用DML触发器监控对表数据库的变更,但是触发器的维护比较困难,性能也不高.2008推出了新功能 变更数据捕获(Change Data Capture,CDC ...

  2. 使用SQL Server更改跟踪创建SQL Server审核

    This continuation of our SQL Server auditing series is on SQL Server Change Tracking and will cover ...

  3. FTPC 在制品跟踪(WIP Tracking)对象

    要执行在制品跟踪(WIP Tracking),必须在Plant Operations中创建代表车间产品的对象.这些称为运行时跟踪对象(Tracking Object).当创建运行时跟踪对象(Track ...

  4. 【专知荟萃18】目标跟踪Object Tracking知识资料全集(入门/进阶/论文/综述/视频/专家,附查看)

    原创: 专知内容组 专知 2017-11-18 点击上方"专知"关注获取专业AI知识! [导读]主题荟萃知识是专知的核心功能之一,为用户提供AI领域系统性的知识学习服务.主题荟萃为 ...

  5. 压缩跟踪Compressive Tracking

    压缩跟踪Compressive Tracking zouxy09@qq.com http://blog.csdn.net/zouxy09 好了,学习了解了稀疏感知的理论知识后,终于可以来学习<R ...

  6. OpenCV平面跟踪planar tracking的实例(附完整代码)

    OpenCV平面跟踪planar tracking的实例 OpenCV平面跟踪planar tracking的实例 OpenCV平面跟踪planar tracking的实例 #include < ...

  7. 压缩跟踪Compressive Tracking源码理解

    压缩跟踪Compressive Tracking源码理解 zouxy09@qq.com http://blog.csdn.net/zouxy09 在前面一个介绍<Real-Time Compre ...

  8. SQL Server 2008中新增的变更数据捕获(CDC)和更改跟踪

    SQL Server 2008中新增的变更数据捕获(CDC)和更改跟踪 SQL Server 2008中SQL应用系列--目录索引 本文主要介绍SQL Server中记录数据变更的四个方法:触发器.O ...

  9. sqlserver更改盘符

    sqlserver更改盘符## 标题 查看当前数据库数据和日志位置 select database_id,name,physical_name AS CurrentLocation,state_des ...

最新文章

  1. typeorm 更新_再热我们也在更新 - Midway 8 月内容汇总
  2. IOS消息机制-委托(ptotocol与delegate)
  3. iOS中UIWebview中网页宽度自适应的问题
  4. SAP Spartacus B2B List里的listData$设计原理
  5. win10mongodb链接_Windows 10 安装 Mongodb
  6. 20190829:(leetcode习题)环形链表
  7. alien rpm deb,ubuntu下安装jdk过程及遇到的问题
  8. 【Visio】 Visio的安装
  9. 关于sockaddr_in 、WSAData 、sockaddr等未定义的问题
  10. 小P的故事——神奇的换零钱 背包
  11. 什么是第三方物流服务?
  12. 你可以跑不赢刘翔,但一定要跑赢CPI
  13. 本地的registry图形化界面harbor安装与使用--02
  14. 交叉线、直通线、反转线的区别与应用
  15. Allegro修改via net
  16. 【贪玩巴斯】带你一起攻克英语语法长难句—— 第一章——简单句详解 2021年12月2日
  17. 腾讯QQ圈子——数据挖掘的典型
  18. 4.DQL查询数据(※重点※)
  19. 如何去除win10此电脑(这台电脑)首页的六个文件夹?
  20. sqlite数据库加锁提交_如何解锁SQLite数据库?

热门文章

  1. 使用JS校验身份证号
  2. 芯片验证从零开始系列(一)——芯片验证概论
  3. 骑马修栅栏(fence) 、铲雪车(snow)
  4. JavaScript面试必问 上
  5. 早会沟通需要注意什么
  6. Windows Server 2008 R2 64bit兼容Chrome浏览器
  7. 企业如何留住客户?精诚CRMPM给你答案
  8. 淘集集活动的报名的链接怎么显示是大于300字呢
  9. pandoc把latex转为word
  10. springMVC中的@ModelAttribute注解