前情提要MS SQL CDC(Change Data Capture)功能初體驗 ,這一篇是要介紹一個CDC須注意的問題, 讓我稍微模擬一下並分享給大家。
CDC其實是跟複寫運用類似的技術,會去LDF讀取LOG後取得所需資料再寫入到CDC的Table中,因此可以想像萬一當CDC卡住無法繼續讀取LDF資料時,LDF檔可是有可能因為這原因無法被Reuse(因為它還有資料尚未被CDC讀走),這時如果您沒注意,那LDF可是有可能會爆掉。
首先我先用dbcc sqlperf(logspace)看一下目前dbCDC資料庫LDF的使用狀況,其檔案為7.9MB,使用量為17%。
下圖中我們可以看見該DB的Log reuse wait desc是nothing。
我接下來故意用Truncate Table語法來清tbCDC資料表資料,可以看見是不能成功的。警告訊息明白指出該Table有被複寫或CDC。因此可以知道複寫跟CDC應該是相同機制。
接下來改用Delete就可以順利清除資料表資料。
清完資料後我故意去改tbCDC資料表的Schema,我將phone欄位由Char(10)改成Char(9),由下圖可以看出異動成功。
這時候我們再一次比對一下tbCDC跟cdc.dbo_tbCDC_CT這兩張資料表的欄位型態是不是還是一樣,如下圖所示tbCDC的phone欄位已經變成Char(9)了,但是cdc.dbo_tbCDC_CT資料表的phone欄位還是Char(10)。因此可以知道上一步驟的Alter Column在cdc.dbo_tbCDC_CT這一張資料表執行失敗。
至於為甚麼cdc.dbo_tbCDC_CT的phone欄位沒有被改為Char(9)呢? 相信您應該也知道,我剛剛是清空tbCDC資料表後才Alter Column,但此時cdc.dbo_tbCDC_CT中是還有資料的 ( CDC資料預設是由一個專門清理的JOB來定時刪除資料,預設是刪除3天前資料 ),尤其phone欄位中皆是10碼的電話紀錄,因此它是無法被改成Char(9)的 ( 會有截斷資料的問題 ),所以之後會因為這一句DDL而導致CDC被卡住。
要知道有無被卡住非常簡單,我直接對tbCDC新增資料來看看cdc.dbo_tbCDC_CT是否有相對應之記錄呢 ? 如下圖所示我直接新增9999筆姓名是Alexis電話是123456789的資料進去tbCDC中。
查詢筆數的確有9999筆
這時我們到cdc.dbo_tbCDC_CT中查詢是否有name為Alexis的資料列,查詢結果如下圖所顯示是0筆。
此時我去看SQL Agent中CDC的Capture的Job會發現一堆的錯誤 ( CDC的Capture Job會不斷去LDF讀取所需的交易紀錄並寫到相對的CDC資料表中 )。
這時我們再用dbcc sqlperf(logspace)來看LDF的使用狀況,會發現LDF長大到71MB了使用量約為18%了。
如下兩張圖所示,即便我對資料庫做交易紀錄備份也於事無補,LDF使用量依然不會下降。
檢視資料庫的Log無法reuse的原因寫的是Replication,再一次證明複寫跟CDC的運作模式應該是一樣的。
即便我下大絕招將資料庫由Full轉成Simple,依然無法解決。所以複寫跟CDC等功能其實跟資料庫的復原模式無關。
最後我只好再加大tbCDC中的phone欄位,將它由Char(9)再改回Char(10)。
然後重新執行CDC的Capture Job
我們可以看見該Capture已經順利的起來了。
這時再去看看資料庫的log reuse wait desc,發現也變成Nothing了。
此時再回去cdc.dbo_tbCDC_CT找是否有name為Alexis的資料,如下圖所示cdc.dbo_tbCDC_CT中已有name為Alexis的資料了。
經過上述簡易LAB操作我們可以了解複寫跟CDC的運作原理應該是一樣,因此也須對CDC這功能是否運行正常要更加注意才行,免得一個不小心就導致LDF爆炸的大災難了。
我是ROCK
rockchang@mails.fju.edu.tw