SQL Server Change Tracking
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的更多相关文章
- 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 ...
- SQL Server审计功能入门:更改跟踪(Change Tracking)
原文:SQL Server审计功能入门:更改跟踪(Change Tracking) 介绍 更改跟踪是一种轻量型解决方案,它为应用程序提供了一种有效的更改跟踪机制.常规的,自定义变更跟踪和读取跟踪数据, ...
- SQL Server审计功能入门:CDC(Change Data Capture)
原文:SQL Server审计功能入门:CDC(Change Data Capture) 介绍 SQL Server 2008引入了CDC(Change Data Capture),它能记录: 1. ...
- 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 ...
- SQL Server 更改跟踪(Chang Tracking)监控表数据
一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 主要区别与对比(Compare) 实现监控表数据步骤(Process) 参考文献(Refere ...
- 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 ...
- SQL Server 2008中的CDC(Change Data Capture)功能使用及释疑
SQL Server 2008中的CDC(Change Data Capture)功能使用及释疑 关键词:CDC 原文:http://www.cnblogs.com/chenxizhang/arc ...
- 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- ...
- 【转载,备忘】SQL Server 更改跟踪(Chang Tracking)监控表数据
一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 主要区别与对比(Compare) 实现监控表数据步骤(Process) 参考文献(Refere ...
随机推荐
- Visual Studio 2017 设置透明背景图
一.前言 给大家分享一下,如何为VS2017设置透明背景图.下面是一张设置前和设置后的图片. 设置前: 设置后: 二.设置背景图片的扩展程序 我们打开VS的扩展安装界面:[工具]->[扩展和更新 ...
- Asp.Net Core SignalR 用泛型Hub优雅的调用前端方法及传参
继续学习 最近一直在使用Asp.Net Core SignalR(下面成SignalR Core)为小程序提供websocket支持,前端时间也发了一个学习笔记,在使用过程中稍微看了下它的源码,不得不 ...
- 在OSGI容器Equinox中嵌入HttpServer
原文地址:https://liugang594.iteye.com/blog/1328050 简单介绍一下如何在一个osgi的bundle中内嵌使用http服务 一.基础 首先看看在OSGI中怎么启动 ...
- Educational Codeforces Round 62 (Rated for Div. 2) - C Playlist
当时题意看错了...不过大致思路是对的,唯一没有想到的就是用优先队列搞这个东西,真是不该啊... 题意大概就是,有N首歌,N首歌有两个东西,一个是长度Ti,一个是美丽值Bi,你最多可以选择K首歌, 这 ...
- 计算机网络基础知识-OSI七层协议模型
一.物理层 物理层主要规定了物理设备的标准,如网线的类型.光纤的接口类型.各种传输介质的传输速率,物理层的数据以比特流(二进制)的形式存在,传输时将比特流转化为电流强弱,达到目的地之后再转化为比特流. ...
- 父元素高度设置为min-height,子元素高度设置为100%,但实际上子元素高度你知道是多少吗?
前言 给父元素一个min-height,子元素设置height:100%. 代码 <!DOCTYPE html> <html> <head> <title&g ...
- SharedPreferences类的使用
SharedPreferences,用xml文件保存用户的偏好设置,是一个轻量级的存储类. 效果图: 代码: activity_main <?xml version="1.0" ...
- 鼠标事件-MouseEvent【转】
原文地址> 鼠标事件-MouseEvent 当鼠标进行某种操作时,就会生成一个event对象,该对象记录着鼠标触发事件时的所有属性. 可以通过如下方法在google控制台打印出 MouseEve ...
- 七牛Qshell 常用命令打印
下载 该工具使用Go语言编写而成,当然为了方便不熟悉Go或者急于使用工具来解决问题的开发者,我们提供了预先编译好的各主流操作系统平台的二进制文件供大家下载使用,由于平台的多样性,我们把这些二进制打包放 ...
- 柳叶刀重磅出击!全外显子测序在胎儿结构异常的评估Whole-exome sequencing in the evaluation of fetal structural anomalies: a prospective cohort study
柳叶刀发表的文献解读:Whole-exome sequencing in the evaluation of fetal structural anomalies: a prospective coh ...