国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發 > 綜合 > 正文

使用更改跟蹤(ChangeTracking)來實現數據類型變更

2024-07-21 02:47:15
字體:
來源:轉載
供稿:網友
使用更改跟蹤(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 TesDB2SET 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 T1GO

3. 對表啟用更改跟蹤

--===================================--對表TB001啟用CT功能ALTER TABLE TB001ENABLE CHANGE_TRACKINGWITH (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 ONINSERT TB002(ID,C1)SELECT ID,C1 FROM TB001SET IDENTITY_INSERT TB002 OFFGO

5. 模擬數據庫上變化,然后將禁用賬戶對表的修改權限

--======================================--模擬TB001上數據變化INSERT INTO TB001(C1)SELECT TOP(100) T1.name FROM sys.all_columns T1GOUPDATE TB001SET C1='UPDATEDATA'WHERE ID%10=1GODELETE TB001WHERE ID%4=1GO

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中插入和更新的數據來更新TB002GOSET 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 TUSING T3 AS SON T.ID=S.IDWHEN 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] OFFGO

8. 檢查兩表數據是否一致,生產環境中建議使用SP_SPACEUSED來查看表數據

--====================================================--檢查數據是否相同,如果下面查詢沒有數據,則證明數據一致SELECT * FROM(    SELECT * FROM TB001    EXCEPT    SELECT * FROM TB002) AS T1UNIONSELECT * FROM(    SELECT * FROM TB002    EXCEPT    SELECT * FROM TB001) AS T2GO

9. 清理測試環境

--==================================--禁用表級別更改跟蹤ALTER DATABASE [TestDB2]SET CHANGE_TRACKING = OFF--==================================--禁用表級別更改跟蹤ALTER TABLE TB001DISABLE CHANGE_TRACKING;--=====================================--刪除測試表DROP TABLE TB001DROP TABLE TB002

由于我們追求的是最終數據一致,因此使用ROW_NUMBER() OVER (PARTITION BY ID ORDER BY CT.SYS_CHANGE_VERSION DESC) AS RowNum =1的方式來過濾中間變更,如果使用SYS_CHANGE_COLMNS會“嚴重”增加代碼復雜性,因此采用更新所有字段的暴力方式實現。

如果導入數據的過程持續時間較長,該期間內數據變化較大,可以考慮先實現一次“同步”后,再禁用舊表的訪問權限,然后再做一次“同步”操作,以降低最后一次“同步”的運行時間。

--============================================================

好久米寫文臟,隨便整個妹子鎮貼。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 新干县| 福建省| 雅江县| 平阴县| 融水| 内江市| 潞城市| 潜山县| 江陵县| 博客| 青川县| 瑞金市| 黔南| 陆丰市| 鸡泽县| 钟山县| 扶风县| 汪清县| 普宁市| 湖口县| 永嘉县| 饶平县| 洛阳市| 安阳县| 巢湖市| 永年县| 长沙市| 广南县| 清原| 嘉鱼县| 拉孜县| 横山县| 龙海市| 安远县| 调兵山市| 金乡县| 黎平县| 江西省| 玉林市| 砚山县| 余庆县|