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. 基于Metronic的Bootstrap开发框架--工作流模块功能介绍(2)

    本篇继续<基于Metronic的Bootstrap开发框架--工作流模块功能介绍>,继续介绍基于Metronic的Bootstrap开发框架的工作模块功能,介绍工作流模块中相关业务表单的界 ...

  2. mybatis 使用缓存策略

    mybatis中默认开启缓存 1.mybatis中,默认是开启缓存的,缓存的是一个statement对象. 不同情况下是否会使用缓存 同一个SqlSession对象,重复调用同一个id的<sel ...

  3. CentOS7下解决yum install mysql-server 异常:No package mysql-server available.问题

    yum安装mysql-server没有可用包问题解决方法: step 1: wget http://repo.mysql.com/mysql-community-release-el7-5.noarc ...

  4. 通过FactoryBean配置Bean

    这是配置Bean的第三种方式,FactoryBean是Spring为我们提供的,我们先来看看源码: 第一个方法:public abstract T getObject() throws Excepti ...

  5. centos7之zabbix3.2搭建

    环境介绍: centos7.4 zabbix3.2 一.zabbix介绍 zabbix官网:https://www.zabbix.com/ zabbix下载页面:https://www.zabbix. ...

  6. photoshop编辑pdf文件

    对于PDF文件透明背景的问题 PDF文件背景是透明的,如何使其变成白色 怎样通过photoshop打开多页PDF,编辑后仍保存为多页 注意shift全选,"页面选项"处的'裁剪到' ...

  7. 越光后端开发——ygapi(2.新建Model)

    1.新建Model 1.users数据 1.在apps/users/models.py中: from datetime import datetime from django.db import mo ...

  8. Gym - 101606G Gentlebots

    Rainforest Inc. is opening a large new automated warehouse in the far Northern reaches of theUK—some ...

  9. sublime text 批量删除空白行

    CTRL+H打开replace功能,勾选上左侧的regular expression,并填写 find what栏 : \s+$  (正则表达式)replace with栏 : (这行留空) 接着点r ...

  10. Kubenetes 资源清单定义入门

    Kubernetes 常用资源 资源  对象 工作负载型资源对象(workload): Pod  Replicaset  ReplicationController  Deployments Stat ...