使用更改跟踪(ChangeTracking)来实现数据类型变更
在现实场景中,我们经常会遇到修改数据类型的场景,尤其是自增列从INT修改为BIGINT的情况,自增列又通常作为表的主键和聚集索引键,因此修改操作需要按以下步骤来进行
1. 停止对该表的访问(通过禁用权限或停应用的方式实现)
2. 删除非聚集索引
3. 删除主键聚集索引
4. 使用ALTER TABLE ALTER COLUMN来修改
5. 创建主键聚集索引
6. 创建非聚集索引
此方式有以下缺点:
1. 整个ALTER COLUMN操作作为一个事务,需要对将每条数据修改操作记录到日志中,中途撤销修改需要长时间回滚。
2. 根据页面碎片情况,修改类型操作可能造成大量的页拆分,导致日志文件暴增。
3. 影响正常业务的周期较长。
针对大事务和页拆分的问题,可以进行以下改进: 新建表,将现有表中数据导入到新表中,数据导入完成后,修改新表名称为现有表名,当仍无法解决影响周期较长的问题,在导入数据期间,允许程序进行只读访问,降低修改类型操作对业务的影响,但数据长时间不可修改,这对很多重要业务也是不可接受的。
为解决此问题,肖桑提出了复制环路的解决办法,采用多级复制的方式,将旧表数据复制到新表中,然后停止旧表读写,等所有修改同步到新表后,再修改表名,以实现数据类型变更的目的,除前期准备时间外,整个操作对业务影响时间可以控制在几分钟以内。
采用导入新表的方式,为保证新旧两表数据一致,必须限制对旧表的修改操作,如果能保证某一时间点的数据被完整地导入到新表,并且保证在导入过程中所有发生在旧表上的操作被“同步”到新表中,那便可以实现新旧两表在特定时间点数据一致。
实现方式:
1. 使用数据库快照来将旧表中某一点的数据导入到新表
2. 使用更改跟踪来将自快照后所有发生在旧表上的数据变更更新到新表上
测试步骤及测试代码:
1. 对数据库启用更改跟踪
--===================================
--对数据库TesDB2启用CT功能
ALTER DATABASE TesDB2
SET CHANGE_TRACKING = ON
(CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON)
GO
2. 创建测试表和生成模拟数据
--=====================================
--创建测试表
CREATE TABLE TB001
(
ID INT IDENTITY(1,1) PRIMARY KEY,
C1 NVARCHAR(200)
)
GO
--==================================
--插入数据
INSERT INTO TB001(C1)
SELECT T1.name FROM sys.all_columns T1
GO
3. 对表启用更改跟踪
--===================================
--对表TB001启用CT功能
ALTER TABLE TB001
ENABLE CHANGE_TRACKING
WITH (TRACK_COLUMNS_UPDATED = ON)
GO
4. 创建新表,并将数据导入到新表中
--==================================
--创建测试表
CREATE TABLE TB002
(
ID BIGINT IDENTITY(1,1) PRIMARY KEY,
C1 NVARCHAR(200)
)
GO
--==================================
--将TB001的数据导入到TB002中
--生产环境可以使用快照方式来保证数据一致性
SET IDENTITY_INSERT TB002 ON
INSERT TB002(ID,C1)
SELECT ID,C1 FROM TB001
SET IDENTITY_INSERT TB002 OFF
GO
5. 模拟数据库上变化,然后将禁用账户对表的修改权限
--======================================
--模拟TB001上数据变化
INSERT INTO TB001(C1)
SELECT TOP(100) T1.name
FROM sys.all_columns T1
GO
UPDATE TB001
SET C1='UPDATEDATA'
WHERE ID%10=1
GO
DELETE TB001
WHERE ID%4=1
GO
6. 将在旧表上的删除操作“同步”到新表上
--======================================
--删除TB001中不存在但在TB002中存在的数据
WITH T1 AS
(
SELECT
ROW_NUMBER() OVER (PARTITION BY ID
ORDER BY CT.SYS_CHANGE_VERSION DESC) AS RowNum,
*
FROM CHANGETABLE(CHANGES [dbo].[TB001],0) AS CT
),
T2 AS
(
SELECT *
FROM T1
WHERE RowNum = 1
AND SYS_CHANGE_OPERATION = 'D'
)
DELETE FROM [dbo].[TB002]
WHERE ID IN (
SELECT ID FROM T2
)
GO
7. 将在旧表上的删除操作“同步”到新表上
--======================================
--根据TB001中插入和更新的数据来更新TB002
GO
SET IDENTITY_INSERT [dbo].[TB002] ON
;WITH T1 AS
(
SELECT
ROW_NUMBER() OVER (PARTITION BY ID
ORDER BY CT.SYS_CHANGE_VERSION DESC) AS RowNum,
*
FROM CHANGETABLE(CHANGES [dbo].[TB001],0) AS CT
),
T2 AS
(
SELECT *
FROM T1
WHERE RowNum = 1
AND (SYS_CHANGE_OPERATION = 'U'
OR SYS_CHANGE_OPERATION = 'I')
),
T3 AS
(
SELECT * FROM [dbo].[TB001]
WHERE ID IN (SELECT ID FROM T2)
),
T4 AS
(
SELECT * FROM [dbo].[TB002]
WHERE ID IN (SELECT ID FROM T2)
)
MERGE T4 AS T
USING T3 AS S
ON T.ID=S.ID
WHEN MATCHED THEN
UPDATE SET T.C1=S.C1
WHEN NOT MATCHED BY TARGET THEN
INSERT(
[ID],
[C1]
)
VALUES
(
[ID],
[C1]
);
SET IDENTITY_INSERT [dbo].[TB002] OFF
GO
8. 检查两表数据是否一致,生产环境中建议使用SP_SPACEUSED来查看表数据
--====================================================
--检查数据是否相同,如果下面查询没有数据,则证明数据一致
SELECT * FROM
(
SELECT * FROM TB001
EXCEPT
SELECT * FROM TB002
) AS T1
UNION
SELECT * FROM
(
SELECT * FROM TB002
EXCEPT
SELECT * FROM TB001
) AS T2
GO
9. 清理测试环境
--==================================
--禁用表级别更改跟踪
ALTER DATABASE [TestDB2]
SET CHANGE_TRACKING = OFF
--==================================
--禁用表级别更改跟踪
ALTER TABLE TB001
DISABLE CHANGE_TRACKING;
--=====================================
--删除测试表
DROP TABLE TB001
DROP TABLE TB002
由于我们追求的是最终数据一致,因此使用ROW_NUMBER() OVER (PARTITION BY ID ORDER BY CT.SYS_CHANGE_VERSION DESC) AS RowNum =1的方式来过滤中间变更,如果使用SYS_CHANGE_COLMNS会“严重”增加代码复杂性,因此采用更新所有字段的暴力方式实现。
如果导入数据的过程持续时间较长,该期间内数据变化较大,可以考虑先实现一次“同步”后,再禁用旧表的访问权限,然后再做一次“同步”操作,以降低最后一次“同步”的运行时间。
--============================================================
好久米写文脏,随便整个妹子镇贴。

使用更改跟踪(ChangeTracking)来实现数据类型变更的更多相关文章
- SQL Server 2008中新增的 1.变更数据捕获(CDC) 和 2.更改跟踪
概述 1.变更数据捕获(CDC) 每一次的数据操作都会记录下来 2.更改跟踪 只会记录最新一条记录 以上两种的区别: http://blog.csdn.n ...
- SQL Server 2008中新增的变更数据捕获(CDC)和更改跟踪
来源:http://www.cnblogs.com/downmoon/archive/2012/04/10/2439462.html 本文主要介绍SQL Server中记录数据变更的四个方法:触发器 ...
- SQL Server 2008新特性——更改跟踪
在大型的数据库应用中,经常会遇到部分数据的脱机和多个数据库的合并问题.比如现在有一个全省范围使用的应用程序,每个市都部署了单独的相同的应用程序服务器和数据库服务器,每个月需要将全省所有市的数据全部汇总 ...
- SQL Server 更改跟踪(Chang Tracking)监控表数据
一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 主要区别与对比(Compare) 实现监控表数据步骤(Process) 参考文献(Refere ...
- SQL Server审计功能入门:更改跟踪(Change Tracking)
原文:SQL Server审计功能入门:更改跟踪(Change Tracking) 介绍 更改跟踪是一种轻量型解决方案,它为应用程序提供了一种有效的更改跟踪机制.常规的,自定义变更跟踪和读取跟踪数据, ...
- 消息 4900,级别 16,状态 2,第 1 行 对表 'XX.XXX' 执行 ALTER TABLE SWITCH 语句失败。对于已启用更改跟踪的表,不可能切换其分区。请先禁用更改跟踪,再使用 ALTER TABLE SWITCH。
问题描述: 今天处理切换分区数据的时候出现了这个错误: 消息 4900,级别 16,状态 2,第 1 行 对表 'XX.XXX' 执行 ALTER TABLE SWITCH 语句失败.对于已启用更改跟 ...
- Dynamics 365 Customer Enagement中的更改跟踪(change tracking)
我是微软Dynamics 365 & Power Platform方面的工程师罗勇,也是2015年7月到2018年6月连续三年Dynamics CRM/Business Solutions方面 ...
- 如何使用块更改跟踪文件估算RMAN增量备份大小 (Doc ID 1938079.1)
How to estimate RMAN incremental backup size using block change tracking file (Doc ID 1938079.1) APP ...
- 【转载,备忘】SQL Server 更改跟踪(Chang Tracking)监控表数据
一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 主要区别与对比(Compare) 实现监控表数据步骤(Process) 参考文献(Refere ...
随机推荐
- js Array 方法总结
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- User_Agent大全
'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Ver ...
- “matplotlib display text must have all code points < 128 or use Unicode strings”解决方法
import sys reload(sys) sys.setdefaultencoding('utf-8') 插入以上代码,便可解决.
- jvm运行机制和volatile关键字详解
参考https://www.cnblogs.com/dolphin0520/p/3920373.html JVM启动流程 1.java虚拟机启动的命令是通过java +xxx(类名,这个类中要有mai ...
- php 制作验证码不显示的问题
php制作验证码的代码,这里就不多说了,网上有很多的,这里说一些可能遇到的问题. 1. 首先是检查自己的php.ini文件,是否支持gd库. 2.保证代码没有出问题. 3.检查字体文件路径是否正确. ...
- 如何将本地代码通过git上传到码云
ps:同部署到GitHub上一样 http://www.cnblogs.com/pcx105/p/7777932.html
- python的6种基本数据类型--集合
特征 1.确定性(元素必须可hash) 2.互异性(去重) 3.无序性(集合中的元素没有顺序,先后之分) >>> s = {1,1,1,2,2,3,4,5,6,7} # 创建 > ...
- c# 动态数组-----“动态”数组
其实在大多数工作中我们能通过前处理来确定我们的数组有多大,这样我们就可以声明相应大小的数组了.我感觉这种“动态”数组就够我用了.比如我要处理excel中数据,数据有m行*n列,这样我就可以通过读取ex ...
- SpringBoot2.0.2 不使用parent作为maven单继承方式操作 : org.springframework.boot : spring-boot-dependencies : 2.0.2.RELEASE
1.pom配置方式 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="h ...
- hadoop hive组件介绍及常用cli命令
Hive架构图 Hive产生原因 1 关系型数据库以产生多年sql成熟 2 简化开发降低成本 3 java成员可编写udf函数 Hive是什么 Hive是基于hadoop的一个数据库工具,使用Hql作 ...