在现实场景中,我们经常会遇到修改数据类型的场景,尤其是自增列从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)来实现数据类型变更的更多相关文章

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

    概述 1.变更数据捕获(CDC)        每一次的数据操作都会记录下来 2.更改跟踪       只会记录最新一条记录   以上两种的区别:         http://blog.csdn.n ...

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

    来源:http://www.cnblogs.com/downmoon/archive/2012/04/10/2439462.html  本文主要介绍SQL Server中记录数据变更的四个方法:触发器 ...

  3. SQL Server 2008新特性——更改跟踪

    在大型的数据库应用中,经常会遇到部分数据的脱机和多个数据库的合并问题.比如现在有一个全省范围使用的应用程序,每个市都部署了单独的相同的应用程序服务器和数据库服务器,每个月需要将全省所有市的数据全部汇总 ...

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

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

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

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

  6. 消息 4900,级别 16,状态 2,第 1 行 对表 'XX.XXX' 执行 ALTER TABLE SWITCH 语句失败。对于已启用更改跟踪的表,不可能切换其分区。请先禁用更改跟踪,再使用 ALTER TABLE SWITCH。

    问题描述: 今天处理切换分区数据的时候出现了这个错误: 消息 4900,级别 16,状态 2,第 1 行 对表 'XX.XXX' 执行 ALTER TABLE SWITCH 语句失败.对于已启用更改跟 ...

  7. Dynamics 365 Customer Enagement中的更改跟踪(change tracking)

    我是微软Dynamics 365 & Power Platform方面的工程师罗勇,也是2015年7月到2018年6月连续三年Dynamics CRM/Business Solutions方面 ...

  8. 如何使用块更改跟踪文件估算RMAN增量备份大小 (Doc ID 1938079.1)

    How to estimate RMAN incremental backup size using block change tracking file (Doc ID 1938079.1) APP ...

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

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

随机推荐

  1. DNSlog盲注

    前言 在渗透测试中,经常遇到如下情景: 1,sql盲注 2,blind型ssrf以及xxe 3,无回显命令执行漏洞 ... dnslog盲注原理 开放的DNSlog平台: http://ceye.io ...

  2. SSRF-php初探

    0x00 前言 1)    SSRF的概念很好理解,请自行百度. 2)    JAVA/PHP/PYTHON都存在SSRF漏洞(至于其他语言的情况,了解粗浅尚不得知). 3)    SSRF的利用方式 ...

  3. 如何用xx-net上youtube

    1.下载https://github.com/XX-net/XX-Net/blob/master/code/default/download.md   里面的稳定版本 2.下载chrome.百度chr ...

  4. JS下拉页面时一个横幅的样式和js

    整理之前的代码,发现有一个js,就是页面往下浏览时,上面的商品名称和购买按钮在页面上方悬浮的,就整理下来,代码如下: <script type="text/javascript&quo ...

  5. Java设计模式(8)——策略模式

    一.策略模式定义 Strategy模式也叫策略模式是行为模式之一,它对一系列的算法加以封装,为所有算法定义一个抽象的算法接口,并通过继承该抽象算法接口对所有的算法加以封装和实现,具体的算法选择交由客户 ...

  6. python学习 day11 (3月16日)----(生成器内置函数)

    1生成器 1生成器的本质 一定是迭代器(反之不一定(用send(生成器特有方法)验证))2生成器是可以让程序员自己定义的一个迭代器3生成器的好处,节省内存空间4生成器的特性,一次性的,惰性机制,从上往 ...

  7. mac挂载ntfs文件系统方法

    1.插入磁盘,并查看 zz@pzdeMacBook-Pro:~/Volumes/ntfs16g$ df Filesystem 512-blocks Used Available Capacity iu ...

  8. 720. Longest Word in Dictionary

    static int wing=[]() { std::ios::sync_with_stdio(false); cin.tie(NULL); ; }(); class Solution { publ ...

  9. 2019.01.04 洛谷P4719 【模板】动态dp(链分治+ddp)

    传送门 ddpddpddp模板题. 题意简述:给你一棵树,支持修改一个点,维护整棵树的最大带权独立集. 思路: 我们考虑如果没有修改怎么做. 貌似就是一个sbsbsb树形dpdpdp,fi,0f_{i ...

  10. pipenv知识积累

    pip install pipenv 安装pipenv pipenv --python 3.6 指定某一Python版本创建环境 pipenv --py 显示Python解释器信息 pipenv -- ...