追蹤記錄每筆業務運算元據改變的利器 SQLCDC

2022-01-16 20:35:13 字數 3362 閱讀 8261

對於大部分企業應用來用,有乙個基本的功能必不可少,那就是audit trail或者audit log,中文翻譯為追蹤檢查、審核檢查或者審核記錄。我們採用audit trail記錄每一筆業務操作的基本資訊,比如操作的基本描述、操作時間、操作者等。對於一些安全級別比較高的應用,或者操作一些比較敏感的資料,我們甚至需要記錄該筆業務操作引起的資料的改變。具體來說,這裡的「資料改變」指的是每一條影響的記錄在操作執行前後的變化。對於新增的記錄,需要記錄下新插入的記錄;對於刪除的記錄,需要記錄下原來的記錄;對於更新的記錄,則需要同時記錄下更新前後的記錄。

說到這裡,很多人都會想到採用觸發器的方式來實現對資料改變的捕捉。但是這種實現方案具有乙個最大的侷限:由於觸發器是在資料操作所在事務範圍內執行的,所有會帶來效能的問題,嚴重的話還會因為觸發器的執行導致事務超市。所以在這裡,我們介紹一種更好的解決方案:sqlcdc。

目錄

一、sqlcdc簡介

二、在資料庫級別開啟cdc

三、為某個資料表開啟cdc

四、記錄新增記錄的資料改變

五、記錄刪除資料的資料改變

六、記錄更新記錄的資料改變

cdc的全名為change data capture,顧名思義,就是用於追蹤和捕捉資料改變。cdc是在sql server 2008中才出現的新特性,而這個特性則在很早之前就出現在了oracle中。對於sql server之前版本來說,在沒有cdc的情況下,如果需要記錄基於某個資料表的資料改變,我們只能採用觸發器,具體來說就是通過手工建立after insert、after update和after delete觸發器去記錄變化的資料。而cdc給了我們一種更為方便、易用和省心的方式去記錄某個資料表的歷史操作。

在預設的情況下,資料庫的cdc特性是被關閉的,你可以通過系統表sys.databases的is_cdc_enabled欄位確定某個資料庫的cdc是否開啟。如果在預設的情況下,我執行如下的sql語句檢視資料庫testdb的cdc是否開啟,你將會看到該字段的值為0。

你可以通過執行系統儲存過程sys.sp_cdc_enable_db為當前資料庫開啟cdc特性。下面的t-sql**片斷中,我們通過執行該儲存過程為testdb開啟了cdc特性。

go
exec sys.sp_cdc_enable_db
go
由於cdc用於記錄基於某個資料表的資料改變,所以在當前資料庫cdc開啟的情況下,你還需要顯式地為某個資料表開啟cdc特性。作為演示,我們通過如下t-sql在testdb下建立了乙個簡單的users表,它僅僅具有三個字段:id、name和birthday。

table [dbo].[users](

[id] [varchar](50) primary

key,

[name] [nvarchar](50) not

null,

[birthday] [date] not

null)

go
exec sys.sp_cdc_enable_table 'dbo', 'users', @role_name = null
go
需要注意的是,cdc實際上建立在sql server agent之上的,所以在執行上述t-sql之前需要啟動sql server agent。當某個資料表的cdc特性被開啟之後,系統會為建立乙個用於儲存資料變化的追蹤表(tracking table)。該錶的schema為cdc,命名方式為被追蹤表的表名後加「ct」字尾。執行上面一段t-sql之後,會有如下乙個系統表被建立出來,我們發現users表的三個欄位也在該表中。此外。該錶還具有5個額外字段:__$start_lsn、__$end_lsn、__$seqval、__$operation 和__$update_mask,表示日誌系列號(log sequence number)、操作(刪除、插入、修改前和修改後)資訊。

現在我們就可以來試驗cdc針對某個資料表的資料改變的捕捉功能了,我們先來試試記錄的新增操作。為此,我們執行如下一段t-sql,插入兩筆user記錄。

values ('001','foo','1981-08-24')
insert into users(id, name, birthday)
values ('002','bar','1981-08-24')
然後通過如下的t-sql檢視cdc.dbo_users_ct表的資料是否將新增操作涉及到的資料改變儲存起來。從查詢結果我們清晰地看到,上面新增的兩筆記錄已經被記錄下來,而__$operation欄位為2表示的是「插入」操作。

接下來我們來cdc對更新操作的追蹤記錄,為此我們通過下面的t-sql改變了使用者foo的birthday。

set birthday = '1982-7-10'
where name = 'foo'
再次執行對於cdc.dbo_users_ct的全表查詢,你會看到這次多了兩筆記錄。其中第3條記錄的是修改之前的資料,而第四條則是修改之後的資料,它們的__$operation欄位德值分別為3和4。

在這裡值得一提的是__$update_mask欄位的值,它表示的記錄更新操作改變的字段。這是乙個以16進製表示的數字,在進行對修改字段進行判斷的時候需要將其轉換成2進製。上述的更新操作對應的__$update_mask值為0x04,轉化成2進製就是100,這三位分別代表3個字段。不過這裡的順序是從右到左,所以100這三位表示的字段為birthday、name和id。1表示改變,0則表示保持不變。由於在上面的t-sql中,我們只改動了birthday,這個和100這個值是吻合的。

我們最後來演示當我們對記錄實施刪除操作的時候,cdc會為我們記錄下怎樣的資料。現在我們執行如下的t-sql將users表中所有的記錄均刪除。

from users

檢視cdc.dbo_users_ct的記錄,多出的兩筆記錄正式我們刪除的user記錄,__$operation欄位的值為1表示「刪除」操作。

乙個完整的用於追蹤資料改變的解決方案

追蹤記錄每筆業務運算元據改變的利器 SQLCDC

對於大部分企業應用來用,有乙個基本的功能必不可少,那就是audit trail或者audit log,中文翻譯為追蹤檢查 審核檢查或者審核記錄。我們採用audit trail記錄每一筆業務操作的基本資訊,比如操作的基本描述 操作時間 操作者等。對於一些安全級別比較高的應用,或者操作一些比較敏感的資料...

使用者運算元據庫記錄

今天我們看看怎樣在資料庫記錄使用者操作 db migrate 002 add audit trails table.rb class addaudittrailstable activerecord migration def self.up create table audit trails do...

185 beego編輯運算元據記錄

beego編輯資料記錄 增加刪除 增加路由 beego.router delete con.get handledelete 然後在控制器中實現刪除 func this articlecontroller handledelete 處理資料 o orm.neworm var article mode...