欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SQLServer 2008 CDC功能實現(xiàn)數(shù)據(jù)變更捕獲腳本

 更新時間:2013年11月24日 15:39:25   作者:  
這篇文章主要介紹了使用SQLServer 2008的CDC功能實現(xiàn)數(shù)據(jù)變更捕獲的腳本,大家參考使用


CDC:Change Data Capture

復制代碼 代碼如下:

--步驟:本文中以GPOSDB為例

--第一步、對目標庫顯式啟用CDC:
--在當前庫使用sys.sp_cdc_enable_db。返回0(成功)或1(失?。?。
--注意,無法對系統(tǒng)數(shù)據(jù)庫和分發(fā)數(shù)據(jù)庫啟用該功能。且執(zhí)行者需要用sysadmin角色權(quán)限。
--該存儲過程的作用域是整個目標庫。包含元數(shù)據(jù)、DDL觸發(fā)器、cdc架構(gòu)和cdc用戶。
--使用以下代碼啟用:
USE GPOSDB  --要啟用CDC的數(shù)據(jù)庫
GO
EXECUTE sys.sp_cdc_enable_db;
GO
--在一開始直接執(zhí)行時,出現(xiàn)了報錯信息:
--消息22830,級別16,狀態(tài)1,過程sp_cdc_enable_db_internal,第193 行
--無法更新元數(shù)據(jù)來指示已對數(shù)據(jù)庫AdventureWorks 啟用了變更數(shù)據(jù)捕獲。
--執(zhí)行命令'SetCDCTracked(Value = 1)' 時失敗。
--返回的錯誤為15517: '無法作為數(shù)據(jù)庫主體執(zhí)行,因為主體"dbo"
--不存在、無法模擬這種類型的主體,或您沒有所需的權(quán)限。'。請使用此操作和錯誤來確定失敗的原因并重新提交請求。
--這里引出了另外一個知識點:錯誤號 15517 的錯誤
--這種錯誤會在很多地方出現(xiàn),如還原數(shù)據(jù)庫的時候也會有可能出現(xiàn)。
--共同點是:某個/些存儲過程使用了具有WITHEXECUTE AS 的選項。
--使其在當前庫具有了某個架構(gòu),但是當在別的地方執(zhí)行時,由于沒有這個架構(gòu),所以就報錯,解決方法:
ALTER AUTHORIZATION ON DATABASE::[GPOSDB] TO [sa]

--經(jīng)過檢查,uspUpdateEmployeeHireInfo這個存儲過程的確有:WITH EXECUTE AS CALLER
--使用sa的原因是即使sa被禁用,sa還是存在的。所以不會報錯。
--現(xiàn)在重新執(zhí)行:
USE GPOSDB
GO
EXECUTE sys.sp_cdc_enable_db;
GO
--啟用成功,然后通過以下語句檢查是否成功:
SELECT
is_cdc_enabled,
CASE WHEN is_cdc_enabled=0 THEN 'CDC功能禁用' ELSE 'CDC功能啟用' END 描述
FROM    sys.databases
WHERE   NAME = 'GPOSDB'

--創(chuàng)建成功后,將自動添加CDC用戶和CDC架構(gòu)。
--在用戶和架構(gòu)下面可以看到cdc用戶和cdc架構(gòu)

--創(chuàng)建這兩個用戶、架構(gòu)的原因是因為CDC要求獨占方式使用這兩個架構(gòu),所以要單獨創(chuàng)建。
--如果存在了非CDC功能創(chuàng)建的CDC用戶、架構(gòu)的話,則需要先刪除該cdc命名的架構(gòu),才能開啟。

--第二步、對目標表啟用CDC:
--使用db_owner角色的成員執(zhí)行sys.sp_cdc_enable_table為每個需要跟蹤的表創(chuàng)建捕獲實例。
--然后通過sys.tables目錄視圖中的is_tracked_by_cdc列來判斷是否創(chuàng)建成功。
--默認情況下會對表的全部列做捕獲。如果只需要對某些列做捕獲,
--可以使用@captured_column_list參數(shù)指定這些列。
--如果要把更改表放到文件組里的話,最好創(chuàng)建單獨的文件組(最起碼與源表獨立)。

--如果不想控制訪問角色,則@role_name必須顯式設(shè)置為null。
sys.sp_cdc_enable_table
    [ @source_schema = ] 'source_schema',
    [ @source_name = ] 'source_name' ,
    [ @role_name = ] 'role_name'
    [,[ @capture_instance = ] 'capture_instance' ]
    [,[ @supports_net_changes = ] supports_net_changes ]
    [,[ @index_name = ] 'index_name' ]
    [,[ @captured_column_list = ] 'captured_column_list' ]
    [,[ @filegroup_name = ] 'filegroup_name' ]
  [,[ @partition_switch = ] 'partition_switch' ]

--例子:
--把SYSTEMPARA 這個表開啟變更捕獲。
USE GPOSDB
GO
EXEC sys.sp_cdc_enable_table @source_schema = 'DBO',
    @source_name = 'SYSTEMPARA',@role_name = NULL

--然后查詢是否成功:
SELECT  name ,
        is_tracked_by_cdc ,
        CASE WHEN is_tracked_by_cdc = 0 THEN 'CDC功能禁用'
             ELSE 'CDC功能啟用'
        END 描述
FROM    sys.tables
WHERE   OBJECT_ID = OBJECT_ID('dbo.systempara')
--對表開啟以后,可以在下圖中看到多了很多cdc架構(gòu)開頭的表:
--刷新一下GPOSDB數(shù)據(jù)庫,在系統(tǒng)表下面可以看到多了下面幾張表
[cdc].[DBO_SYSTEMPARA_CT]
[cdc].[change_tables]
[cdc].[captured_columns]
[cdc].[ddl_history]
[cdc].[index_columns]
[cdc].[lsn_time_mapping]
[dbo].[systranschemas]
[dbo].[dtproperties]

--啟動之后,可以看到SQLServer代理里面的作業(yè),也出現(xiàn)了這兩個作業(yè):
[cdc.GPOSDB_capture]
[cdc.GPOSDB_cleanup]

--在可編程性-》函數(shù)-》表值函數(shù)里,也多了兩個函數(shù)
[cdc].[fn_cdc_get_all_changes_DBO_SYSTEMPARA]
[cdc].[fn_cdc_get_net_changes_DBO_SYSTEMPARA]

--下面列出相關(guān)的存儲過程:
--Sys.sp_cdc_add_job
--說明及例子
--Sys.sp_cdc_generate_wrapper_function
--說明及例子
--Sys.sp_cdc_change_job
--說明及例子
--Sys.sp_cdc_get_captured_columns
--說明及例子
--Sys.sp_cdc_cleanup_change_table
--說明及例子
--Sys.sp_cdc_get_ddl_history
--說明及例子
--Sys.sp_cdc_disable_db
--說明及例子  建議先禁用表,再禁用庫
--Sys.sp_cdc_help_change_data_capture
--說明及例子
--Sys.sp_cdc_disable_table
--說明及例子
--Sys.sp_cdc_help_jobs
--說明及例子
--Sys.sp_cdc_drop_job
--說明及例子
--Sys.sp_cdc_scan
--說明及例子
--Sys.sp_cdc_enable_db
--說明及例子
--Sys.sp_cdc_start_job
--說明及例子
--Sys.sp_cdc_enable_table
--說明及例子
--Sys.sp_cdc_stop_job
--說明及例子

--函數(shù):
--Cdc.fn_cdc_get_all_changes_<capture_instance>
--說明及例子
--Sys.fn_cdc_has_column_changed
--說明及例子
--Cdc.fn_cdc_get_net_changes_<capture_instance>
--說明及例子
--Sys.fn_cdc_increment_lsn
--說明及例子
--Sys.fn_cdc_decrement_lsn
--說明及例子
--Sys.fn_cdc_is_bit_set
--說明及例子
--Sys.fn_cdc_get_column_ordinal
--說明及例子
--Sys.fn_cdc_map_lsn_to_time
--說明及例子
--Sys.fn_cdc_get_max_lsn
--說明及例子
--Sys.fn_cdc_map_time_to_lsn
--說明及例子
--Sys.fn_cdc_get_min_lsn
--說明及例子

--------------------下面開始從頭到尾做一個實際案例-------------------------
--下面開始從頭到尾做一個實際案例

--步驟一:對目標庫顯式啟用CDC
USE GPOSDB  --要啟用CDC的數(shù)據(jù)庫
GO
EXECUTE sys.sp_cdc_enable_db;
GO


--某些數(shù)據(jù)庫可能存在一些存儲過程包含有:execute as 等語句,此時會報錯:


--文字描述:
--消息22830,級別16,狀態(tài)1,過程sp_cdc_enable_db_internal,第186 行
--無法更新元數(shù)據(jù)來指示已對數(shù)據(jù)庫AdventureWorks 啟用了變更數(shù)據(jù)捕獲。執(zhí)行命令'SetCDCTracked(Value = 1)' 時失敗。返回的錯誤為15517: '無法作為數(shù)據(jù)庫主體執(zhí)行,因為主體"dbo" 不存在、無法模擬這種類型的主體,或您沒有所需的權(quán)限。'。請使用此操作和錯誤來確定失敗的原因并重新提交請求。
--消息266,級別16,狀態(tài)2,過程sp_cdc_enable_db_internal,第0 行
--EXECUTE 后的事務計數(shù)指示BEGIN 和COMMIT 語句的數(shù)目不匹配。上一計數(shù)= 0,當前計數(shù)= 1。
--消息266,級別16,狀態(tài)2,過程sp_cdc_enable_db,第0 行
--EXECUTE 后的事務計數(shù)指示BEGIN 和COMMIT 語句的數(shù)目不匹配。上一計數(shù)= 0,當前計數(shù)= 1。
--消息3998,級別16,狀態(tài)1,第1 行
--在批處理結(jié)束時檢測到不可提交的事務。該事務將回滾。
--如果出現(xiàn)這個錯誤,目前的解決方法是執(zhí)行下面語句,原因已在開頭說明,對于沒有使用EXECUTE AS的庫,一般不會有這樣的問題:


ALTER AUTHORIZATION ON DATABASE::[GPOSDB] TO [sa]

--現(xiàn)在重新執(zhí)行:
USE GPOSDB
GO
EXECUTE sys.sp_cdc_enable_db;
GO
--通過以下語句檢查是否成功:
SELECT
is_cdc_enabled,
CASE WHEN is_cdc_enabled=0 THEN 'CDC功能禁用' ELSE 'CDC功能啟用' END 描述
FROM    sys.databases
WHERE   NAME = 'GPOSDB'

--步驟二:對表啟用CDC
USE GPOSDB
GO
EXEC sys.sp_cdc_enable_table
@source_schema = 'DBO',
@source_name = 'SYSTEMPARA',
@role_name = NULL,
@capture_instance=DEFAULT
GO

--然后查詢是否成功:
SELECT  name ,
        is_tracked_by_cdc ,
        CASE WHEN is_tracked_by_cdc = 0 THEN 'CDC功能禁用'
             ELSE 'CDC功能啟用'
        END 描述
FROM    sys.tables
WHERE   OBJECT_ID = OBJECT_ID('dbo.systempara')

--可以看到GPOSDB數(shù)據(jù)庫里的系統(tǒng)表里新增了[cdc].[DBO_SYSTEMPARA_CT]表

 

 

--步驟三:檢驗,下面來改動數(shù)據(jù)
--先查詢一下DBO_SYSTEMPARA_CT表
SELECT * FROM cdc.[DBO_SYSTEMPARA_CT]

--可以看到一條記錄都沒有,因為剛剛創(chuàng)建,并沒有對原表systempara做任何增刪改操作

--向[SystemPara]表插入一條記錄
INSERT INTO [dbo].[SystemPara]
        ( [ParaValue] ,
          [Name] ,
          [Description]
        )
VALUES  ( '中國' , -- ParaValue - varchar(50)
          '中國' , -- Name - varchar(50)
          '中國'  -- Description - varchar(50)
        )

--查詢一下DBO_SYSTEMPARA_CT表,可以看到多了一條記錄
SELECT * FROM cdc.[DBO_SYSTEMPARA_CT]


--更新[SystemPara]表的一條記錄
UPDATE [dbo].[SystemPara] SET [ParaValue]='德國' WHERE [Description]='中國'

--查詢一下DBO_SYSTEMPARA_CT表,可以看到多了兩條記錄
SELECT * FROM cdc.[DBO_SYSTEMPARA_CT]

--刪除[SystemPara]表的一條記錄
DELETE FROM  [dbo].[SystemPara]  WHERE [Description]='中國'

--查詢一下DBO_SYSTEMPARA_CT表,可以看到多了一條記錄
SELECT * FROM cdc.[DBO_SYSTEMPARA_CT]

--現(xiàn)在來分析一下DBO_SYSTEMPARA_CT表
--可以在聯(lián)機叢書上查看:
--cdc.<capture_instance>_CT 
--可以看到,這樣命名的表,是用于記錄源表做過更改操作的表。
--對于insert/delete操作,會有對應的一行記錄,而對于update,會有兩行記錄。
--對于__$operation列:1 = 刪除、2= 插入、3= 更新(舊值)、4= 更新(新值)
--update語句的__$operation列的值是3和4,所以一條update語句對應兩條記錄

--對于__$start_lsn列:由于更改是來源與數(shù)據(jù)庫的事務日志,所以這里會保存其事務日志的開始序列號(LSN)
--但是微軟不檢查直接查詢這類表,建議使用
--cdc.fn_cdc_get_all_changes_<捕獲實例>
--cdc.fn_cdc_get_net_changes_<capture_instance>
-- 來查詢

----------------------------------------------------------

--下文開始,來熟悉各種函數(shù)、存儲過程的使用,并嘗試一些不正常的操作。

 

--日常使用情景:
--1、查詢已經(jīng)開啟的捕獲實例:
--返回所有表的變更捕獲配置信息
USE [GPOSDB]
GO
EXECUTE sys.sp_cdc_help_change_data_capture;
GO

 

--查看對某個實例(即表)的哪些列做了捕獲監(jiān)控
USE [GPOSDB]
GO
EXEC sys.sp_cdc_get_captured_columns
@capture_instance = 'systempara' -- sysname

 

--也可以從下面中查找配置信息
SELECT * FROM msdb.dbo.cdc_jobs

 

 


--2、查看當前配置使用sp_cdc_help_jobs:
--從上文可以看到,啟用cdc之后會自動創(chuàng)建了兩個作業(yè),可以先使用以下語句來查看:
sp_cdc_help_jobs

 

--對于一個大型的OLTP系統(tǒng),由于數(shù)據(jù)更改會非常頻繁,變更表中的數(shù)據(jù)會非常多,
--如果存放過久(最久可以存放100年),那對數(shù)據(jù)庫空間是非常大的挑戰(zhàn)。
--此時可以調(diào)整上圖中cdc.AdventureWorks_cleanup 中retention(單位:分鐘)。

--3、修改配置:sp_cdc_change_job
--顯示原有配置
EXEC sp_cdc_help_jobs
GO
--更改數(shù)據(jù)保留時間為100分鐘
EXECUTE sys.sp_cdc_change_job
    @job_type = N'cleanup',
    @retention=100
GO

--重啟一下作業(yè),以使設(shè)置生效
--停用作業(yè)
EXEC sys.sp_cdc_stop_job N'cleanup'
GO
--啟用作業(yè)
EXEC sys.sp_cdc_start_job N'cleanup'
GO
--再次查看
EXEC sp_cdc_help_jobs
GO
--可以看到retention(單位:分鐘)的值變?yōu)?00了

--4、停止/啟用、刪除/創(chuàng)建作業(yè)

--停用作業(yè)
EXEC sys.sp_cdc_stop_job N'cleanup'
GO
--啟用作業(yè)
EXEC sys.sp_cdc_start_job N'cleanup'
GO

--刪除作業(yè)
EXEC sys.sp_cdc_drop_job @job_type = N'cleanup' -- nvarchar(20)
GO
--查看作業(yè)
EXEC sys.sp_cdc_help_jobs
GO
--可以看到現(xiàn)在只剩下一個作業(yè)了:cdc.GPOSDB_capture


--創(chuàng)建作業(yè)
EXEC sys.sp_cdc_add_job
    @job_type = N'cleanup',
    @start_job = 0,
    @retention = 5760

--查看作業(yè)
EXEC sys.sp_cdc_help_jobs
GO

 

--5、DDL變更捕獲:
--CDC除了捕獲數(shù)據(jù)變更之外,還能捕獲DDL操作的變化。
--前提是先要確保SQLServer 代理的啟用,其實CDC功能都需要確保sql 代理正常運行
--因為所有操作都通過代理中的兩個作業(yè)來實現(xiàn)的。
--現(xiàn)在先來對SYSTEMPARA 表修改一下,把PARAVALUE的長度加長
USE [GPOSDB]
GO
ALTER TABLE  [dbo].[SystemPara] ALTER COLUMN PARAVALUE VARCHAR(120) ;
GO

--然后查詢ddl記錄表
SELECT  * FROM    cdc.ddl_history


--6、使用CDC的函數(shù)來獲取更改
--A、使用 [cdc].[fn_cdc_get_all_changes_DBO_SYSTEMPARA]
--函數(shù)報告捕獲實例的當前所有可用更改
DECLARE @from_lsn BINARY(10) ,
    @to_lsn BINARY(10)
SET @from_lsn = sys.fn_cdc_get_min_lsn('SYSTEMPARA')
SET @to_lsn = sys.fn_cdc_get_max_lsn()
SELECT  *
FROM    cdc.fn_cdc_get_all_changes_DBO_SYSTEMPARA(@from_lsn, @to_lsn,N'all update old');
GO

 


--B、獲取某個時間段的更改信息:
--先根據(jù)日志序列號(logsequence number ,LSN)來獲取跟蹤變更數(shù)據(jù)
--Sys.fn_cdc_map_time_to_lsn獲取變更范圍內(nèi)的最大、最小LSN值??梢允褂?BR>Smallest greater than;
smallest greater than orequal;
largest less than;
largest less than or equal;

--如查詢某個時間段插入的數(shù)據(jù)
INSERT INTO [dbo].[SystemPara]
        ( [ParaValue] ,
          [Name] ,
          [Description]
        )
VALUES  ( '中國' , -- ParaValue - varchar(50)
          '中國' , -- Name - varchar(50)
          '中國'  -- Description - varchar(50)
        )

GO

--檢查數(shù)據(jù)
--1刪除
--2插入
--3、4更改
--曾經(jīng)插入過的記錄就算delete了也可以查詢出來
DECLARE @bglsn VARBINARY(10)= sys.fn_cdc_map_time_to_lsn('smallest greater than or equal',
                                                         '2013-10-21 12:00:00.997')
DECLARE @edlsn VARBINARY(10)= sys.fn_cdc_map_time_to_lsn('largest less than or equal',
                                                         GETDATE())
SELECT  *
FROM    [cdc].[DBO_SYSTEMPARA_CT]
WHERE   [__$operation] = 2
        AND [__$start_lsn] BETWEEN @bglsn AND @edlsn

 

--C、sys.fn_cdc_map_lsn_to_time 查詢變更時間:
SELECT  [__$operation] ,
        CASE [__$operation]
          WHEN 1 THEN '刪除'
          WHEN 2 THEN '插入'
          WHEN 3 THEN '更新(捕獲的列值是執(zhí)行更新操作前的值)'
          WHEN 4 THEN '更新(捕獲的列值是執(zhí)行更新操作后的值)'
        END [類型] ,
        sys.fn_cdc_map_lsn_to_time([__$start_lsn]) [更改時間] ,
        *
FROM    [cdc].[DBO_SYSTEMPARA_CT]

 

--D、獲取LSN邊界
SELECT  sys.fn_cdc_get_max_lsn() [數(shù)據(jù)庫級別的最大LSN] ,
        sys.fn_cdc_get_min_lsn('cdc.DBO_SYSTEMPARA_CT') [捕獲實例的lsn]


這兩個值可以用于上面提到的函數(shù)里面用于篩選數(shù)據(jù)之用。


----------------------------------------------------------
--1. CDC的目的是什么?

--CDC就是極大地方便了我們獲取某個表數(shù)據(jù)更新情況的一個機制。它通過一個獨立的進程,
--異步讀取日志文件,而不是觸發(fā)器的方式工作。而且它的數(shù)據(jù)是會持久化保存到一個系統(tǒng)表的。
--2. CDC是不是SQL Server 2008特有的功能,對別的數(shù)據(jù)庫或者早期版本是否起作用?

--CDC是SQL Server 2008特有的功能,而且是企業(yè)版特有的功能。開發(fā)版也有該功能,但僅用于測試場合。

--3. CDC讀取日志,那么如果日志被截斷了會怎么樣?

--如果某部分日志,CDC的進程還沒有讀取,那么在截斷日志時就會忽略這個部分,不能截斷!!

--捕獲進程是一個獨立的,它隨著代理服務啟動而啟動。兩次掃描之間間隔5分鐘。

--4. 系統(tǒng)表中的數(shù)據(jù)是否會永久存在?--不會,它會被保留3天。會有一個清理的作業(yè),每天晚上2點進行掃描。
--最后,補充一點的是,CDC功能依賴Agent服務,因為它有兩個操作都是通過作業(yè)來啟動的。

相關(guān)文章

最新評論