我們在讀寫數據庫文件時,當文件被讀、寫或者出現錯誤時,這些過程活動都會觸發一些運行時事件。從一個用戶角度來看,有些時候會關注這些事件,特別是我們調試、審核、服務維護。例如,當數據庫錯誤出現、列數據被更新、CPU占用過高等,跟蹤這些狀態是非常有用地。
本章節覆蓋了事件系統的關鍵區域:觸發器、事件通知器、改變跟蹤、SQL跟蹤、擴展事件等。這些事件都有一個相似目的:響應或者記錄發生的事件。但每一中事件的工作方式又不一樣。
基礎:觸發器和事件通知器
觸發器非常多,Data Manipulation Language (DML) triggers定義於當插入、更新數據時激發一個操作;Data Definition Language (DDL)
triggers 定義於當服務器或者數據庫級活動發生時激發某個操作,例如登陸或者刪除某張表。DML觸發器能激發代替觸發中的事件,或者當這個事件完成后但是沒有提交時。DDL triggers只能配置成事件已經完成但事物沒有提交。事件通知器和DDL Trigger相似,不同的一重要點是它不需要任何Transaction,作為一個結果支持非事物事件。例如一個用戶斷開和數據庫的連接。
改變跟蹤
首先舉一個例:有些系統需要把數據庫緩存在本地,同時要求隨時關注數據庫數據是否有更新,能夠隨時保持緩存和數據庫的同步。這種情況更多的實現方式是使用觸發器或者時間戳。但這樣設計也會經常帶來問題問題。例如,如果時間戳列在插入數據時統計而不是在提交時統計時,時間戳經常失效。這樣存在的問題是,如果一個大數據插入的同時其他小數據也在插入,但這個大數據提交比小數據提交慢。因此影響了時間戳的自然排序。觸發器可以解決一些問題,但是它也增加了事物的提交時間。
Change Tancking被設計用來跟蹤單表或者多表的數據變化。讓用戶方便的決定改變觸發的順序。它作為事物的一部分同步跟蹤改變發生。
Change Tracking基於基線工作的思想。數據客戶首先請求跟蹤表里邊所有行的當前狀態也得到了每一行的版本號。基線版本號是系統知道的當前最大的版本號。直到下一個同步器請求時它會被同步,當這個請求發生,基線版本號被發送回到Change Tracking系統,通過比對跟蹤表裂變的版本和基線表里邊的版本確定該系統哪些行已經被修改自從第一次請求。
Sql Server 2008包括兩個相似的技術用來支持同步:Change Tracking和Change Data Capture。Change Tracking支持離線應用,也支持某些連接的應用以及其他不需要實時通知當數據被更新。
改變跟蹤配置
改變跟蹤配置有兩個配置級別,一個是數據庫配置級別,另外一個是表配置級別。
1)數據庫配置級別。可以使用sql指令ALTER DTABASE來修改變化跟蹤配置 ,數據庫默認是啟動了跟蹤配置,我們可以執行以下指令啟動跟蹤:
ALTER DATABASE heavi_case1
SET CHANGE_TRACKING = ON;
說明:執行這條語句后,一旦表級別跟蹤啟動后將跟蹤兩個變化:第一個,一個隱藏的系統表將用來跟蹤目標數據庫;第二個,一個清理任務將開始評估相關表里邊是否遺留比較久的行數據。
a)隱藏的系統表
這個隱藏的表叫做提交表(Commit Table),它為在變化跟蹤里邊出現的每一個數據庫提交事物生成一個行數據。當事物發生,一個等量的事物被標記,它包含一個唯一標識、序列標識(Commit Sequence Number,CSN)。CSN隨着事物標示、日期序列信息、開始時間、其他數據一起插入到Commit Table中。這個表主要用來提供數據給改變跟蹤(Change Tracking)和幫助決策當一個用戶請求一個更新時哪個改變將要被同步。
我們可以通過sys.all_columns目錄視圖查看Commit Table的列和索引。Commit Table的歷史名稱叫做sys.syscommitab。我們可以執行以下語句:
SELECT *
FROM sys.all_columns
WHERE object_id = OBJECT_ID('sys.syscommittab');
執行結果如下:


sys.syscommitab有兩個索引:一個聚集索引在commit_ts和xdes_id列上,一個非聚集索引在xdes_id上。
必須說明的是Commit Table值存儲事物信息,而沒有存儲真實的行數據。這些相關的數據是存儲在分割的系統表中。因為一個事物能聯合多個表並且每個表可能有多行數據,如果都存儲在Commit Table中那么數據量會非常大。Commit Table中所有的列除了dbfragid,都可以通過動態管理試圖(DMV)sys.dm_tran_commit_table來查詢。
b)內部清理任務
一旦Commit生成了數據,這些數據也將占據數據庫一定內存。Change Tracking包含功能啟動內部任務來處理哪些不需要的歷史數據。我們可通過以下sql來配置:
ALTER DATABASE heavi_case1
SET CHANGE_TRACKING = ON
(AUTO_CLEANUP=ON, CHANGE_RETENTION=1 hours);
如果可用,內存任務每30分鍾執行一次,評估哪些事務需要被移除(通過當前時間減去保留時間得到一個時間差,然后通過一個接口從Commit Table中找出時間范圍大於時間差的事物ID,最后通過事物ID從Commit Table和其他隱藏表中移除事物)。
清理任務配置可通過以下sql查詢:
select * from sys.change_tracking_databases;
2)表級配置
要為某一個表啟動表級別配置。可通過ALTER TABLE和ENABLE CHANGE_TRACKING配置。例如,我們為hvi_Order表啟動配置:
ALTER TABLE hvi_Order ENABLE CHANGE_TRACKING;
如果Change Tracking啟動了數據庫級配置,當運行這條語句會產生兩個變化。第一,數據庫會創建一個內部表跟蹤目標表的行數據事物。第二,一個隱藏的列被增加到目標表,通過事物ID跟蹤特殊行變化。
被創建的內部表命名規則為sys.change_tracking_[object_id],object id可通過sys.all_objects目錄視圖查找。或者通過sys.internal_tables查找(條件為internal_type等於209)。sql語句分別如下:
select distinct * from sys.all_objects where parent_object_id in
(select object_id from sys.all_objects where [name] like 'hvi_Order') # 我這樣寫便於大家識別


select * from sys.internal_tables where parent_object_id in
(select object_id from sys.all_objects where [name] like 'hvi_Order')


上面我們說到別級別還會雜目標表中增加額外的8字節列記錄最新的事物ID。如果Change tracking關閉,該列也會被移除。
改變跟蹤運行時行為
Change Tracking啟動表級別后附加的修改了每一個DML操作行為。也可以通過CHANGETABLE允許數據用戶找出哪些行發生了變化並需要同步。
接下來我們往hvi_Order表中插入一行數據,同時查看執行計划過程。
sql語句:insert into dbo.hvi_Order(createtime, cus_id) values('2015/11/1', 2);
查詢分析過程:

我們比對下沒有啟動表級別跟蹤的表插入數據執行分析過程:


可以看出,啟動表級別跟蹤后,執行過程會通過內部變化表如果有輸入插入更新。
跟蹤和Profiling(沒明白中文意思)
查詢調整、優化、一般故障解決都可以通過可見的過程產生。SQL Trace是一個比較強大的工具用來提供查詢數據庫引擎正在做什么。通過跟蹤工具,我們可以監視180個事件。在這些事件中,我們可以通過特殊的session id(SPID)查看用戶登錄、鎖活動的細節信息。這些數據通過SQL Server Profiler生成,以及一系列的服務端存儲過程和.NET classes,並且可以提供給你靈活性回滾自定義的解決方法當出現問題。
SQL Trace是一個數據庫引擎技術,必須要理解的一點是常常客戶端配置工具僅僅是去封裝了服務端的功能。在跟蹤時,當各種活動出現在數據庫引擎中,我們監視各種事件。例如,一個用戶登錄或者執行查詢的每一個活動都會出發事件去捕獲。並且這些事件是通過數據庫引擎代碼去捕獲。換一種說法,特殊的代碼已經被添加到執行路徑中,通過這些代碼出發事件。例如一個查詢案例,當查詢開始我們能收集數據,包括查詢執行時間、占用CPU多少時間。
Sql Server來龍去脈系列目錄結構:
Sql Server來龍去脈系列之五 日志以及恢復
Sql Server來龍去脈系列之六 表
Sql Server來龍去脈系列之七 索引
Sql Server來龍去脈系列之八 比較特殊的存儲
Sql Server來龍去脈系列之九 查詢優化
Sql Server來龍去脈系列之十 計划緩存
Sql Server來龍去脈系列之十一 事務和並發