sqlserver 的cdc功能


變更數據捕獲(Change Data Capture ,簡稱 CDC)記錄 SQL Server 表的插入、更新和刪除活動。SQLServer的操作會寫日志,這也是CDC捕獲數據的來源


開啟cdc的源表在插入、更新和刪除活動時會插入數據到日志表中。cdc通過捕獲進程將變更數據捕獲到變更表中,通過cdc提供的查詢函數,我們可以捕獲這部分數據。
同時也可以捕獲ddl的修改
附一個測試用的sql文件(來源於debezium 工具的sqlserver腳本,工具類似mysql的canal和maxwell。) https://files.cnblogs.com/files/wang2650/testdbsql.zip
####### 開啟CDC的必要條件
1 sqlserver 2008 以上版本
2 需要開啟代理服務(作業)
3 磁盤要有足夠的空間,保存日志文件
4 表必須要有主鍵或者是唯一索引
####### 開啟數據庫CDC
1、 在需要開啟cdc的數據庫上執行腳本如下:

if exists(select 1 from sys.databases where name='db_name' and is_cdc_enabled=0)
begin
    exec sys.sp_cdc_enable_db
end

2、查詢數據庫的cdc開啟狀態

select is_cdc_enabled from sys.databases where name='db_name'

查詢結果為“1”,表示開啟成功。

開啟表CDC

*注意:表中必須有主鍵或者唯一索引

1、添加次要數據文件組及文件
數據庫右鍵“屬性” >> “文件組”>> ”添加”


“文件” >> “添加”

2、執行以下腳本,開啟表cdc

--CDC是數據庫文件組的名稱
IF EXISTS(SELECT 1 FROM sys.tables WHERE name='table_name' AND is_tracked_by_cdc = 0)
BEGIN
    EXEC sys.sp_cdc_enable_table
        @source_schema = 'dbo', -- source_schema
        @source_name = 'table_name', -- table_name
        @capture_instance = NULL, -- capture_instance
        @supports_net_changes = 1, -- supports_net_changes
        @role_name = NULL, -- role_name
        @index_name = NULL, -- index_name
        @captured_column_list = NULL, -- captured_column_list
        @filegroup_name = 'CDC' -- filegroup_name
END

3、查看表cdc開啟狀態

SELECT is_tracked_by_cdc FROM sys.tables WHERE name='table_name'

查詢結果為“1”,表示開啟成功。

三、使用CDC

開啟cdc后會在數據庫中生成以下文件,開啟數據庫GY_DB,開啟表VW_GHZDK

下面我們會對部分表和函數進行說明

系統表:

cdc.change_tables:表開啟cdc后會插入一條數據到這張表中,記錄表一些基本信息
cdc.captured_columns:開啟cdc后的表,會記錄它們的字段信息到這張表中
cdc.dbo_VW_GHZDK_CT:記錄VW_GHZDK表中所有變更的數據,
字段“$operation”為“1”代表刪除,“2”代表插入,“3”執行更新操作前的值,“4”執行更新操作后的值。
字段“
$start_lsn”由於更改是來源於數據庫的事務日志,所以這里會保存其事務日志的開始序列號(LSN)
字段 __$update_mask : 表示那個列做了操作,02 就是0010 表示第二列 ,那07就是 0111 表示123列都做了修改羅

注意,當修改了表結構,例如字段類型等會有問題,最好從心做一個捕獲實例

參考文章 https://www.cnblogs.com/tiancai/p/11996801.html

可以在聯機叢書上查看:cdc.<capture_instance>_CT 可以看到,這樣命名的表,是用於記錄源表更改的表。對於insert/delete操作,會有對應的一行記錄,而對於update,會有兩行記

函數:

cdc.fn_cdc_get_all_changes_dbo_VW_GHZDK:針對在指定日志序列號 (LSN) 范圍內應用到源表的每項更改均返回一行。如果源行在該間隔內有多項更改,則每項更改都會表示在返回的結果集中

cdc.fn_cdc_get_net_changes_dbo_VW_GHZDK:針對指定 LSN 范圍內每個已更改的源行返回一個凈更改行。也就是說,如果在 LSN 范圍內源行具有多項更改,則該函數將返回反映該行最終內容的單一行

sys.fn_cdc_map_time_to_lsn:為指定的時間返回 cdc.lsn_time_mapping 系統表中 start_lsn 列中的日志序列號 (LSN) 值。可以使用此函數系統地將日期時間范圍映射到基於 LSN 的范圍,以供變更數據捕獲枚舉函數 cdc.fn_cdc_get_all_changes_<capture_instance> 和 cdc.fn_cdc_get_net_changes_<capture_instance> 返回此范圍內的數據更改。

以上文章參考 https://www.cnblogs.com/maikucha/p/9039205.html
https://blog.csdn.net/dba_huangzj/article/details/8130448 這個文章更詳細

其他

停止/開始作業,可以使用以下語句:

--停用作業
EXEC sys.sp_cdc_stop_jobN'cleanup'
GO
--啟用作業
EXEC sys.sp_cdc_start_jobN'cleanup'
GO

--對作業的更改 非常重要 尤其是retention參數。
EXEC sys.sp_cdc_change_job
  @job_type = 'capture'
  ,@maxtrans = 1000      --每個掃描循環可以處理的最多事務數
  ,@maxscans = 10        --為了從日志中提取所有行而要執行的最大掃描循環次數
  ,@continuous = 1       --連續運行最多處理(max_trans * max_scans) 個事務
  ,@pollinginterval = 5
 

EXEC sys.sp_cdc_change_job
@job_type = 'cleanup'
,@retention = 4320 --更改行將在更改表中保留的分鍾數
,@threshold = 5000 --清除時可以使用一條語句刪除的刪除項的最大數量

刪除作業:

EXEC sys.sp_cdc_drop_job@job_type = N'cleanup' -- nvarchar(20)
GO
--查看作業
EXEC sys.sp_cdc_help_jobs
GO

創建作業:

EXEC sys.sp_cdc_add_job
    @job_type = N'cleanup',
    @start_job = 0,
    @retention = 5760
--查看作業
EXEC sys.sp_cdc_help_jobs
GO

查看表是否啟用了CDC

select name, is_tracked_by_cdc from sys.tables where object_id = OBJECT_ID('dbo.t1')

禁用表(“dbo.t1”)

EXEC sys.sp_cdc_disable_table @source_schema = 'dbo', @source_name = 't1', @capture_instance = 'all';

禁用數據庫CDC

EXEC sys.sp_cdc_disable_db; 

根據發布批量生成表

SELECT 'EXEC sys.sp_cdc_enable_table @source_schema = N'''+b.source_owner+''','
+'@source_name='''+b.source_object+''','+'@role_name=''cdc'',@supports_net_changes = 1'
FROM dbo.MSpublications a,dbo.MSarticles b
WHERE a.publication_id=b.publication_id AND a.publisher_db=b.publisher_db
and a.publication ='his_repl'

ddl的捕獲

ELECT  * FROM    cdc.ddl_history

根據系統表批量生成表

select 'EXEC sys.sp_cdc_enable_table @source_schema = ''dbo'', @source_name = '''+name+''', @role_name = null;'
from sysobjects where xtype='U' and category ='0'

獲取某個時間段的更改信息: 先根據日志序列號(logsequence number ,LSN)來獲取跟蹤變更數據:
Sys.fn_cdc_map_time_to_lsn獲取變更范圍內的最大、最小LSN值。可以使用: Smallest greater than;smallest greater than orequal;largest less than;largest less than or equal.

如查詢某個時間段插入的數據:

--插入數據

INSERT INTO HumanResources.Department(name,GroupName,ModifiedDate)

VALUES('test','abc',GETDATE())

INSERT INTO HumanResources.Department(name,GroupName,ModifiedDate)

VALUES('test1','abc1',GETDATE())

go

--檢查數據

DECLARE @bglsn VARBINARY(10)=sys.fn_cdc_map_time_to_lsn('smallest greater than or equal','2012-10-12 12:00:00.997')

DECLARE @edlsn VARBINARY(10)=sys.fn_cdc_map_time_to_lsn('largest less than or equal',GETDATE())

SELECT DepartmentID,GroupName,Name

FROM cdc.HumanResources_Department_CT

WHERE [__$operation]=2 AND [__$start_lsn] BETWEEN @bglsn AND @edlsn

sys.fn_cdc_map_lsn_to_time 查詢變更時間:

SELECT  [__$operation] ,
       CASE [__$operation] WHEN 1 THEN '刪除' WHEN 2 THEN '插入' WHEN 3 THEN '更新(捕獲的列值是執行更新操作前的值)'
     WHEN 4 THEN '更新(捕獲的列值是執行更新操作后的值)' END [類型],
  sys.fn_cdc_map_lsn_to_time([__$start_lsn]) [更改時間] ,
        name , DepartmentID , GroupName , ModifiedDate
FROM    cdc.HumanResources_Department_CT

獲取LSN邊界:

SELECT sys.fn_cdc_get_max_lsn()[數據庫級別的最大LSN],

sys.fn_cdc_get_min_lsn('cdc.HumanResources_Department_CT')[捕獲實例的lsn]

結果如下:

這兩個值可以用於上面提到的函數里面用於篩選數據之用。

原文 https://www.cnblogs.com/zzchao/p/10918494.html

查詢 : 最好給表加一個自增長的主鍵或者通過關聯lsn_time_mapping表,獲取指定時間內的操作日志。

 select top  100 * from [testdb].[cdc].[dbo_userinfo_ct] where [__$start_lsn]>0x0000002e000004


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM