1 概述

“更改跟踪”和“变更数据捕获”捕获和记录用户表的DML更改(插入、更新和删除操作),为某些有特殊需求的应用程序服务。

1.1 更改跟踪

更改跟踪捕获表的数据行更改这一行为,但不会捕获更改的具体数据。捕获的结果包含表的主键及相关的跟踪信息(例如更改的操作类型、更新操作影响的列等)。

应用程序可以利用这个捕获的结果来确定表的最新更新,并可以关联原始来来获取最新的数据。

1.2 变更数据捕获

变更数据捕获使用异步进程读取事务日志,获取DML更改实际数据做为数据捕获的结果。在捕获结果中,还包含更改相关的一些信息(例如更改的操作类型、更新操作影响的列等)。

应用程序可以从捕获结果中获取DML更改的全部数据,而无需查询数据变更的原始表。

1.3 比较更改跟踪和变更数据捕获

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

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

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

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

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

2 使用

下面用两个示例简单说明更改跟踪和变更数据捕获的配置及变更信息的查询。

2.1 更改跟踪

更改跟踪的配置如下:

a. 在数据库上启用更改跟踪(ALTER DATABASE … CHANGE_TRACKING = ON),并设置跟踪结果保持期;

b. 在需要跟踪更改的每个表上启用更改跟踪(ALTER TABLE … ENABLE CHANGE_TRACKING),并设置是否要求记录UPDATE的列信息。(启用更改跟踪的表需要有主键)。

更改跟踪结果的查询包括:

a. CHANGE_TRACKING_CURRENT_VERSION

返回与上次提交的事务相关联的版本号。启用了更改跟踪的数据库具有一个版本计数器,在对启用了更改跟踪的表进行更改时,该计数器会随之递增。每个更改的行都有一个关联的版本号。可以在每次查询完成后,记录这个版本号,下次查询时,基于这个版本号查询,以获取后续的最新更改。

b. CHANGE_TRACKING_MIN_VALID_VERSION

指定表可用的最低有效版本号。在第一次查询数据的时候,可以使用此函数得到查询更改信息的起始版本号;

c. CHANGETABLE(CHANGES)

返回自指定版本起对表所做的所有更改的跟踪信息;

d. CHANGETABLE(VERSION)

返回指定行的最新更改跟踪信息。(通过指定特定行对应的主键列值);

e. CHANGE_TRACKING_IS_COLUMN_IN_MASK

通过CHANGETABLE(CHANGES …)函数返回的SYS_CHANGE_COLUMNS值及列id,确定该列是否被UPDATE。

下面的T-SQL示例创建一个测试数据库,并在测试数据库中演示配置更改跟踪及查询更改跟踪信息。

-- ====================================================
-- 测试的数据库
USE master;
GO
CREATE DATABASE DB_test;
GO
ALTER DATABASE DB_test SET
CHANGE_TRACKING = ON(
AUTO_CLEANUP = ON, -- 打开自动清理选项
CHANGE_RETENTION = 1 HOURS -- 数据保存期为1 时
);
GO
-- ====================================================
-- 测试的表
USE DB_test;
GO
CREATE TABLE dbo.tb(
id int
CONSTRAINT PK_tb_id PRIMARY KEY,
col1 int,
col2 varchar(10),
col3 nvarchar(max),
col4 varbinary(max),
col5 xml
);
GO
ALTER TABLE dbo.tb
ENABLE CHANGE_TRACKING
WITH(
TRACK_COLUMNS_UPDATED = ON -- 记录UPDATE 的列信息
);
GO
SELECT
CHANGE_TRACKING_CURRENT_VERSION(),
CHANGE_TRACKING_MIN_VALID_VERSION(OBJECT_ID(N'dbo.tb'));
GO
-- ====================================================
-- 数据测试
-- a. 插入初始数据
INSERT dbo.tb(
id,
col1, col2, col3, col4, col5)
VALUES(
1,
1, 'AA', 'AAA', 0x1, '<a>aa</a>'),
(
2,
2, 'BB', 'BBB', 0x2, '<b/>'),
(
3,
3, 'CC', 'CCC', 0x2, '<c/>');
SELECT
CHANGE_TRACKING_CURRENT_VERSION(),
CHANGE_TRACKING_MIN_VALID_VERSION(OBJECT_ID(N'dbo.tb')),
*
FROM CHANGETABLE(CHANGES dbo.tb, 0) CHG
LEFT JOIN dbo.tb DATA
ON DATA.id = CHG.id;
-- b. 更新数据
BEGIN TRAN;
UPDATE dbo.tb SET
col1 = 11
WHERE id = 1;
UPDATE dbo.tb SET
col1 = 111
WHERE id = 1;
COMMIT TRAN;
SELECT
CHANGE_TRACKING_CURRENT_VERSION(),
CHANGE_TRACKING_MIN_VALID_VERSION(OBJECT_ID(N'dbo.tb')),
*
FROM CHANGETABLE(CHANGES dbo.tb, 0) CHG
LEFT JOIN dbo.tb DATA
ON DATA.id = CHG.id;
-- c. 更新xml 和varbinary(max) 数据
UPDATE dbo.tb SET
col5.modify('replace value of /a[1]/text()[1] with "replace"')
WHERE id = 1;
UPDATE dbo.tb SET
col5.modify('insert <a>1</a> as last into /')
WHERE id = 2;
SELECT
CHANGE_TRACKING_CURRENT_VERSION(),
CHANGE_TRACKING_MIN_VALID_VERSION(OBJECT_ID(N'dbo.tb')),
*
FROM CHANGETABLE(CHANGES dbo.tb, 0) CHG
LEFT JOIN dbo.tb DATA
ON DATA.id = CHG.id;
UPDATE dbo.tb SET
col4 = col4 + 0x12345
WHERE id = 3;
SELECT
CHANGE_TRACKING_CURRENT_VERSION(),
CHANGE_TRACKING_MIN_VALID_VERSION(OBJECT_ID(N'dbo.tb')),
*
FROM CHANGETABLE(CHANGES dbo.tb, 0) CHG
LEFT JOIN dbo.tb DATA
ON DATA.id = CHG.id;
-- d. 更新主键
UPDATE dbo.tb SET
id = 11
WHERE id = 1;
INSERT dbo.tb(
id,
col1, col2, col3, col4, col5)
VALUES(
1,
1, 'AA', 'AAA', 0x1, '<a>aa</a>')
SELECT
CHANGE_TRACKING_CURRENT_VERSION(),
CHANGE_TRACKING_MIN_VALID_VERSION(OBJECT_ID(N'dbo.tb')),
*
FROM CHANGETABLE(CHANGES dbo.tb, 0) CHG
LEFT JOIN dbo.tb DATA
ON DATA.id = CHG.id;
SELECT
CHANGE_TRACKING_CURRENT_VERSION(),
CHANGE_TRACKING_MIN_VALID_VERSION(OBJECT_ID(N'dbo.tb')),
*
FROM dbo.tb DATA
OUTER APPLY CHANGETABLE(VERSION dbo.tb, (id), (DATA.id)) CHG
-- ====================================================
-- 删除测试
/*--
USE master;
GO
ALTER DATABASE DB_test SET
SINGLE_USER
WITH
ROLLBACK AFTER 0;
GO
DROP DATABASE DB_test;
--*/

2.2 变更数据捕获

变更数据捕获配置如下:

a. 在数据库上启用变更数据捕获(调用系统存储过程sys.sp_cdc_enable_db);

b. 通过系统存储过程sys.sp_cdc_add_job创建捕获和清理Job(可选,如果没有捕获和清理Job,会在创建数据库中的第一个变更数据捕获时自动建立,自动建立的Job可以通过调用系统存储过程sys.sp_cdc_change_job来调整捕获和清理相关的一些选项);

c. 在需要捕获变更数据的每个表上建立变更数据捕获实例(每个表上可以建立<=2个捕获实例,创建捕获实例使用系统存储过程sys.sp_cdc_enable_table)。

捕获的变更数据的查询包括:

a. sys.fn_cdc_get_min_lsn

返回指定捕获实例的有效性间隔的低端点(start_lsn);

b. sys.fn_cdc_get_max_lsn

返回cdc.lsn_time_mapping系统表的最大日志序列号(LSN);

c. cdc.fn_cdc_get_all_changes_<捕获实例>

针对在指定日志序列号(LSN)范围内应用到源表的每项更改均返回一行。如果源行在该间隔内有多项更改,则每项更改都会表示在返回的结果集中。除了返回更改数据外,四个元数据列还提供了将更改应用到另一个数据源所需的信息。行筛选选项可控制元数据列的内容以及结果集中返回的行。当指定“all”行筛选选项时,针对每项更改将只有一行来标识该更改。当指定“all update old”选项时,更新操作会表示为两行:一行包含更新之前已捕获列的值,另一行包含更新之后已捕获列的值。

此枚举函数是在对源表启用变更数据捕获时创建的。此函数名称是派生的,采用cdc.fn_cdc_get_all_changes_capture_instance格式,其中capture_instance是在对源表启用变更数据捕获时为捕获实例指定的值;

d. cdc.fn_cdc_get_net_changes_<capture_instance>

针对指定日志序列号(LSN)范围内每个已更改的源行返回一个净更改行。净更改行指:如果在LSN范围内源行具有多项更改,则该函数将返回反映该行最终内容的单一行。例如,如果事务在源表中插入一行,并且LSN范围内的后续事务更新了该行中的一个或多个列,则该函数将只返回一行,其中包含多个更新的列值。

此枚举函数是在对某源表启用变更数据捕获并指定净跟踪时创建的。函数名称是派生的,采用cdc.fn_cdc_get_net_changes_capture_instance格式,其中capture_instance是对变更数据捕获启用源表时为捕获实例指定的值;

e. sys.fn_cdc_map_time_to_lsn

为指定的时间返回cdc.lsn_time_mapping系统表中start_lsn列中的日志序列号(LSN)值;

f. sys.fn_cdc_has_column_changed

标识指定的更新掩码是否指示已更新关联的更改行中的指定列。

下面的T-SQL示例创建一个测试数据库,并在测试数据库中演示配置变更数据捕获及查询捕获结果。

-- ====================================================
-- 测试的数据库
USE master;
GO
CREATE DATABASE DB_test;
GO
-- 启用变更数据捕获
USE DB_test;
EXEC sys.sp_cdc_enable_db;
GO
-- ====================================================
-- 检查SQL Server Agent 服务的状态,如果未启动,则启动它
DECLARE
@agnt_service sysname;
SET @agnt_service = N'SQLServerAgent';
DECLARE @tb_agent_status TABLE(
state varchar(50)
);
INSERT @tb_agent_status
EXEC master.sys.xp_servicecontrol
N'QUERYSTATE',
@agnt_service;
IF NOT EXISTS(
SELECT * FROM @tb_agent_status
WHERE state = N'Running.')
EXEC master.sys.xp_servicecontrol
N'START',
@agnt_service;
GO
-- ====================================================
-- 测试的表
USE DB_test;
GO
CREATE TABLE dbo.tb(
id int
CONSTRAINT PK_tb_id PRIMARY KEY,
col1 int,
col2 varchar(10),
col3 nvarchar(max),
col4 varbinary(max),
col5 xml
);
GO
-- 创建一个变更数据捕获实例- 所有列
-- 创建数据库中的第一个变更数据捕获实例的时候,数据捕获和清理的JOB 会自动创建
-- 可以通过sys.sp_cdc_change_job 这个存储过程去调整捕获和清理的相关设置
-- 也可以在创建第一个变更数据捕获实例前,使用sys.sp_cdc_add_job去创建数据捕获和清理Job,在创建时做好相关的设置
EXEC sys.sp_cdc_enable_table
@source_schema = N'dbo',
@source_name = N'tb',
@capture_instance = N'dbo_tb',
@role_name = NULL;
-- 创建一个变更数据捕获实例- 特定列
EXEC sys.sp_cdc_enable_table
@source_schema = N'dbo',
@source_name = N'tb',
@capture_instance = N'dbo_tb_col',
@role_name = NULL,
@captured_column_list = N'id,col1,col2';
GO
-- ====================================================
-- 数据测试
-- a. 插入初始数据
INSERT dbo.tb(
id,
col1, col2, col3, col4, col5)
VALUES(
1,
1, 'AA', 'AAA', 0x1, '<a>aa</a>'),
(
2,
2, 'BB', 'BBB', 0x2, '<b/>'),
(
3,
3, 'CC', 'CCC', 0x2, '<c/>');
WITH
LSN AS(
SELECT
from_lsn = sys.fn_cdc_get_min_lsn(N'dbo_tb'),
to_lsn = sys.fn_cdc_get_max_lsn()
),
CHG_ALL AS(
SELECT
CHG.*
FROM LSN
CROSS APPLY cdc.fn_cdc_get_all_changes_dbo_tb(LSN.from_lsn, LSN.to_lsn, 'ALL UPDATE OLD') CHG
),
CHG_NET AS(
SELECT
CHG.*
FROM LSN
CROSS APPLY cdc.fn_cdc_get_net_changes_dbo_tb(LSN.from_lsn, LSN.to_lsn, 'ALL') CHG
)
SELECT * FROM CHG_ALL;
-- b. 更新数据
BEGIN TRAN;
UPDATE dbo.tb SET
col1 = 11
WHERE id = 1;
UPDATE dbo.tb SET
col1 = 111
WHERE id = 1;
COMMIT TRAN;
WITH
LSN AS(
SELECT
from_lsn = sys.fn_cdc_get_min_lsn(N'dbo_tb'),
to_lsn = sys.fn_cdc_get_max_lsn()
),
CHG_ALL AS(
SELECT
CHG.*
FROM LSN
CROSS APPLY cdc.fn_cdc_get_all_changes_dbo_tb(LSN.from_lsn, LSN.to_lsn, 'ALL UPDATE OLD') CHG
),
CHG_NET AS(
SELECT
CHG.*
FROM LSN
CROSS APPLY cdc.fn_cdc_get_net_changes_dbo_tb(LSN.from_lsn, LSN.to_lsn, 'ALL') CHG
)
SELECT * FROM CHG_ALL;
-- c. 更新xml 和varbinary(max) 数据
UPDATE dbo.tb SET
col5.modify('replace value of /a[1]/text()[1] with "replace"')
WHERE id = 1;
UPDATE dbo.tb SET
col5.modify('insert <a>1</a> as last into /')
WHERE id = 2;
UPDATE dbo.tb SET
col4 = col4 + 0x12345
WHERE id = 3;
WITH
LSN AS(
SELECT
from_lsn = sys.fn_cdc_get_min_lsn(N'dbo_tb'),
to_lsn = sys.fn_cdc_get_max_lsn()
),
CHG_ALL AS(
SELECT
CHG.*
FROM LSN
CROSS APPLY cdc.fn_cdc_get_all_changes_dbo_tb(LSN.from_lsn, LSN.to_lsn, 'ALL UPDATE OLD') CHG
),
CHG_NET AS(
SELECT
CHG.*
FROM LSN
CROSS APPLY cdc.fn_cdc_get_net_changes_dbo_tb(LSN.from_lsn, LSN.to_lsn, 'ALL') CHG
)
SELECT * FROM CHG_ALL;
-- d. 更新主键
UPDATE dbo.tb SET
id = 11
WHERE id = 1;
INSERT dbo.tb(
id,
col1, col2, col3, col4, col5)
VALUES(
1,
1, 'AA', 'AAA', 0x1, '<a>aa</a>');
WITH
LSN AS(
SELECT
from_lsn = sys.fn_cdc_get_min_lsn(N'dbo_tb'),
to_lsn = sys.fn_cdc_get_max_lsn()
),
CHG_ALL AS(
SELECT
CHG.*
FROM LSN
CROSS APPLY cdc.fn_cdc_get_all_changes_dbo_tb(LSN.from_lsn, LSN.to_lsn, 'ALL UPDATE OLD') CHG
),
CHG_NET AS(
SELECT
CHG.*
FROM LSN
CROSS APPLY cdc.fn_cdc_get_net_changes_dbo_tb(LSN.from_lsn, LSN.to_lsn, 'ALL') CHG
)
SELECT * FROM CHG_ALL;
-- ====================================================
-- 删除测试
/*--
USE master;
GO
ALTER DATABASE DB_test SET
SINGLE_USER
WITH
ROLLBACK AFTER 0;
GO
DROP DATABASE DB_test;
--*/

SQL Server Change Tracking的更多相关文章

  1. P6 Professional Installation and Configuration Guide (Microsoft SQL Server Database) 16 R1

    P6 Professional Installation and Configuration Guide (Microsoft SQL Server Database) 16 R1       May ...

  2. SQL Server审计功能入门:更改跟踪(Change Tracking)

    原文:SQL Server审计功能入门:更改跟踪(Change Tracking) 介绍 更改跟踪是一种轻量型解决方案,它为应用程序提供了一种有效的更改跟踪机制.常规的,自定义变更跟踪和读取跟踪数据, ...

  3. SQL Server审计功能入门:CDC(Change Data Capture)

    原文:SQL Server审计功能入门:CDC(Change Data Capture) 介绍 SQL Server 2008引入了CDC(Change Data Capture),它能记录: 1. ...

  4. Change the Target Recovery Time of a Database (SQL Server) 间接-checkpoints flushcache flushcache-message

    Change the Target Recovery Time of a Database (SQL Server) 间接checkpoints   flushcache flushcache-mes ...

  5. SQL Server 更改跟踪(Chang Tracking)监控表数据

    一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 主要区别与对比(Compare) 实现监控表数据步骤(Process) 参考文献(Refere ...

  6. To fix sql server 2008 r2 Evaluation period has expired by change the key

    PTTFM-X467G-P7RH2-3Q6CG-4DMYB 数据中心版:PTTFM-X467G-P7RH2-3Q6CG-4DMYB   测试可用 开 发者 版:MC46H-JQR3C-2JRHY-XY ...

  7. SQL Server 2008中的CDC(Change Data Capture)功能使用及释疑

    SQL Server 2008中的CDC(Change Data Capture)功能使用及释疑 关键词:CDC   原文:http://www.cnblogs.com/chenxizhang/arc ...

  8. Easy way to change collation of all database objects in SQL Server

    This info is from: http://www.codeproject.com/Articles/302405/The-Easy-way-of-changing-Collation-of- ...

  9. 【转载,备忘】SQL Server 更改跟踪(Chang Tracking)监控表数据

    一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 主要区别与对比(Compare) 实现监控表数据步骤(Process) 参考文献(Refere ...

随机推荐

  1. service docker start后docker stop/waiting的解决方法

    在某次强行对机子断电后,再开机后发现docker没启动 运行service docker start显示docker start/running, process xxxx,之后不一会儿就停止了, 再 ...

  2. yafu安装使用方法以及mismatched parens解决方法

    yafu用于自动整数因式分解,在RSA中,当p.q的取值差异过大或过于相近的时候,使用yafu可以快速的把n值分解出p.q值,原理是使用Fermat方法与Pollard rho方法等. 再摘录官方的一 ...

  3. iOS开发基础-九宫格坐标(3)之Xib

    延续iOS开发基础-九宫格坐标(2)的内容,对其进行部分修改. 本部分采用 Xib 文件来创建用于显示图片的 UIView 对象. 一.简单介绍  Xib 和 storyboard 的比较: 1) X ...

  4. 安装软件the error code is 2203解决方法

    win10安装mysql5.7的时候弹出这个2203错误,记录一下. 解决方法: 按照下面路径,去掉只读解决了.

  5. 如何卸载VS 2017之前版本比如VS 2013、VS2015、 VS vNext?

    前言 大学专业为软件工程,进入大学之后才知道这个专业需要用到笔记本,我的笔记本配置为I3,内存4个G,已经有大几年了,中间坏了修了一次一直用到现在,这个笔记本还是我哥打工过年回来身上仅有的三四千块钱所 ...

  6. day02(编程语言,解释器,环境变量,执行方式,pycharm,pip,变量三大组成)

      上节课复习: 重点: 1,进制转换:二进制与十六进制 2,内存分布:栈区 与 堆区 10101001110111 => 2a77 abf1 => 1010101111110001 计算 ...

  7. [第二届构建之法论坛] 预培训文档(C++版)

    本博客是第二届构建之法论坛暨软件工程培训活动预培训文档中[适用于结对编程部分的C++版本],需要实验者有一部分C++基础. 目录 Part0.背景 Part1.配置环境 Part2.克隆项目 Part ...

  8. Shell命令-线上查询及帮助之man、help

    线上查询及帮助 - man.help 1.man:获取命令的帮助信息 man命令的简单介绍 man命令是Linux系统中最核心的命令之一 ,因为通过它可以查看其它Linux命令的使用信息.当然了 ,m ...

  9. js DOM操作 容易犯的错误

    这样一段html片段 <select class="form-control" id="course_chapter" onchange="fi ...

  10. 返回通知 对方法返回的结果可以进行加工 例如请求接口后 返回的json参数可以加工成对象返回给调用者