前言
一提到跟蹤倆字,很多人想到警匪片中的場景,同樣在我們的SQL Server數據庫中“跟蹤”也是無處不在的,如果我們利用好了跟蹤技巧,就可以針對某些特定的場景做定向分析,找出充足的證據來破案。
簡單的舉幾個應用場景:
在線生產庫為何突然宕機?數百張數據表為何不翼而飛?剛打好補丁的系統為何屢遭黑手?新添加的信息表為何頻頻丟失?某張表字段的突然更改,究竟為何人所為?這些個匿名的訪問背后,究竟是人是鬼?突然增加的增量數據,究竟是對是錯?數百兆的日志爆炸式的增長背后又隱藏著什么?這一且的背后,是應用程序的BUG還是用戶品質的缺失?
請關注本篇文章,讓我們一起利用數據庫的“跟蹤”(Trace)走進數據庫背后,查看其內部原理。
我相信如用過SQL Server數據庫的人,都會或多或少的利用過SQL Profiler工具。這個玩意就是利用SQL Trace形成的一個圖形化操作工具,我們直接進入本篇的正題。
一.查看系統默認跟蹤信息(Default Trace)
Trace作為一個很好的數據庫追蹤工具,在SQL Server 2005中便集成到系統功能中去,并且默認是開啟的,當然我們也可以手動的關掉它,它位于sp_config配置參數中,我們可以通過以下語句查看:
select * from sys.configurations where configuration_id = 1568
我們也可以通過下面的語句找到這個跟蹤的記錄
select * from sys.traces
如果沒有開啟,我們也可以利用如下語句進行開啟,或者關閉等操作
--開啟Default Trace sp_configure 'show advanced options' , 1 ; GO RECONFIGURE; GO sp_configure 'default trace enabled' , 1 ; GO RECONFIGURE; GO --測試是否開啟 EXEC sp_configure 'default trace enabled'; GO --關閉Default Trace sp_configure 'default trace enabled' , 0 ; GO RECONFIGURE; GO sp_configure 'show advanced options' , 0 ; GO RECONFIGURE; GO
通過以下命令找到默認跟蹤的文件路徑
select * from ::fn_trace_getinfo(0)
以上命令返回的結果值,各個值(property)代表的含義如下:
第一個:2表示滾動文件;
第二個:表示當前使用的trace文件路徑,根據它我們可以找到其它的跟蹤文件,默認是同一目錄下
第三個:表示滾動文件的大小(單位MB),當到達這個值就會創建新的滾動文件
第四個:跟蹤的停止時間,這里為Null,表示沒有固定的停止時間
第五個:當前跟蹤的狀態:0 停止;1 運行
找到該目錄,我們查看下該文件:
、
系統默認提供5個跟蹤文件,并且每一個文件默認大小都是20MB,SQL Server會自己維護這5個文件,當實例重啟的時候或者到達最大值的時候,之后會重新生成新的文件,將最早的跟蹤文件刪除,依次滾動更新。
我們通過以下命令來查看跟蹤文件中的內容:
默認的跟蹤文件,提供的跟蹤信息還是很全的,從中我們可以找到登錄人,操作信息等,上面的截圖只是包含的部分信息。我們可以利用該語句進行自己的加工,然后獲得更有用的信息。
--獲取跟蹤文件中前100行執行內容 SELECT TOP 100 gt.[HostName] ,gt.[ServerName] ,gt.[DatabaseName] ,gt.[SPID] ,gt.[ObjectName] ,gt.[objecttype] [ObjectTypeID] ,sv.[subclass_name] [ObjectType] ,e.[category_id] [CategoryID] ,c.[Name] [Category] ,gt.[EventClass] [EventID] ,e.[Name] [EventName] ,gt.[LoginName] ,gt.[ApplicationName] ,gt.[StartTime] ,gt.[TextData] FROM fn_trace_gettable('E:\dataDefaultFileManger\MSSQL10.MSSQLSERVER\MSSQL\Log\log_1267.trc', DEFAULT) gt LEFT JOIN sys.trace_subclass_values sv ON gt.[eventclass] = sv.[trace_event_id] AND sv.[subclass_value] = gt.[objecttype] INNER JOIN sys.trace_events e ON gt.[eventclass] = e.[trace_event_id] INNER JOIN sys.trace_categories c ON e.[category_id] = c.[category_id] WHERE gt.[spid] > 50 AND --50以內的spid為系統使用 gt.[DatabaseName] = 'master' AND --根據DatabaseName過濾 gt.[ObjectName] = 'fn_trace_getinfo' AND --根據objectname過濾 e.[category_id] = 5 AND --category 5表示對象,8表示安全 e.[trace_event_id] = 46 --trace_event_id --46表示Create對象(Object:Created), --47表示Drop對象(Object:Deleted), --93表示日志文件自動增長(Log File Auto Grow), --164表示Alter對象(Object:Altered), --20表示錯誤日志(Audit Login Failed) ORDER BY [StartTime] DESC
我創建了一張表,通過上面的跟蹤,可以跟蹤到該記錄的信息,根據不同的過濾信息,我們可以查詢出到跟蹤的某個庫的某個表的更改信息,包括:46創建(Created)、47刪除(Deleted)、93文件自動增長信息(Log File Auto Grow)、146修改(Alter)、20表示錯誤日志(Login Failed)
在生產環境中,以上幾個分類都是比較常用的,對定位部分問題的定位能夠在找到充分的證據可循,比如某廝將數據庫數據刪除掉了還不承認等,這里面的Login Failed信息,能夠追蹤出有那么用戶嘗試登陸過數據庫,并且失敗,如果大面積的出現這種情況,那就要謹防黑客襲擊了。
當然,這里我還可以利用SQL Server自帶的Profile工具,打開查看跟蹤文件中的內容。
這個圖像化的工具就比較熟悉了,直接打開進行篩選就可以了。
這種方式看似不錯,但是它也有本身的缺點,我們來看:
1、這5個文件是滾動更新的,而且每個文件默認最大都為20MB,并且沒有提供更改的接口,所以當文件填充完之后就會刪除掉,所以會找不到太久以前的內容;
2、本身默認的跟蹤,只是提供一些關鍵信息的追蹤,其中包括:auditing events,database events,error events,full text events,object creation,object deletion,object alteration,想要找到其它更詳細的內容,此方式可能無能為力;
3、在SQL Server2012后續版本的 Microsoft SQL Server 將刪除該功能,改用擴展事件。
二.自定義跟蹤信息(Default Trace)
根據上面SQL Server自帶的跟蹤信息有一些局限性,SQL Server為我們提供了自定義跟蹤的接口,我們可以自己定義跟蹤,充分擴展方法。
利用如下系統存儲過程,我們可以創建自定義的Trace
sp_trace_create [ @traceid = ] trace_id OUTPUT , [ @options = ] option_value , [ @tracefile = ] 'trace_file' [ , [ @maxfilesize = ] max_file_size ] [ , [ @stoptime = ] 'stop_time' ] [ , [ @filecount = ] 'max_rollover_files' ]
@traceid 系統默認分配跟蹤的ID號
@options 指定為跟蹤設置的選項,系統默認提供的幾個選項:
2表示當文件寫滿的時候,關閉當前跟蹤并創建新文件。
4表示如果不能將跟蹤寫入文件,不管什么原因導致,SQL Server則會關閉。這個可以利用此選項,追蹤問題
8制定服務器產生的最后5MB的跟蹤信息記錄由服務器保存。
@tracefile 跟蹤文件的路徑,這里可以是share的路徑
@maxfilesize 跟蹤文件的大小,單位是MB,默認不設置為5MB
@stoptime 跟蹤停止的時間,利用它我們可以定時跟蹤結束的日期
@filecount 默認生產的跟蹤文件的數量,比如默認的為5個,那就在第5個文件寫完的時候進行覆蓋第1個文件滾動
比如我們可以利用如下腳本進行創建
--創建跟蹤文件返回值 declare @rc int --創建一個跟蹤句柄 declare @TraceID int --創建跟蹤文件路徑 declare @TraceFilePath nvarchar(500) set @TraceFilePath=N'F:\SQLTest\' --跟蹤文件的大小 declare @maxfilesize bigint set @maxfilesize=5 --設置停止的時間 declare @EndTime datetime set @EndTime=null --設置系統默認的操作 declare @options int set @options=2 --設置默認滾動文件的數目 declare @filecount int set @filecount=5 exec @rc=sp_trace_Create @TraceID output, @options, @TraceFilePath, @maxfilesize, @EndTime, @filecount if(@rc=0) select @TraceID
我們通過上面的跟蹤創建的過程,可以在系統自帶的默認的sys.traces中找到該跟蹤的明細
select * from sys.traces where id=2
通過上面的腳本,我們已經創建了一個新的跟蹤(trace),但是這個跟蹤狀態為0,也就是說還沒有運行,下面我們的步驟就是要為這個跟蹤添加事件(event)
這個也是利用SQL Server為我們提供的操作函數
sp_trace_setevent [ @traceid = ] trace_id , [ @eventid = ] event_id , [ @columnid = ] column_id , [ @on = ] on
@traceid 要修改的跟蹤的 ID號
@eventid 要打開的事件的 ID
@columnid 要為該事件添加的列的 ID
@on 表示事件狀態
其中最主要的就是時間ID,這個是SQL Server為我們提供的一些列的碼表時間值,具體值可以參考聯機叢書 sp_trace_setevent (Transact-SQL)
這里面最常用的就是:
事件號 |
事件名稱 |
說明 |
---|---|---|
10 |
RPC:Completed |
在完成了遠程過程調用 (RPC) 時發生。 |
11 |
RPC:Starting |
在啟動了 RPC 時發生。 |
12 |
SQL:BatchCompleted |
在完成了 Transact-SQL 批處理時發生。 |
13 |
SQL:BatchStarting |
在啟動了 Transact-SQL 批處理時發生。 |
14 |
Audit Login |
在用戶成功登錄到 SQL Server 時發生。 |
15 |
Audit Logout |
在用戶從 SQL Server 注銷時發生。 |
16 |
Attention |
在發生需要關注的事件(如客戶端中斷請求或客戶端連接中斷)時發生。 |
17 |
ExistingConnection |
檢測在啟動跟蹤前連接到 SQL Server 的用戶的所有活動。 |
18 |
Audit Server Starts and Stops |
在修改 SQL Server 服務狀態時發生。 |
20 |
Audit Login Failed |
指示試圖從客戶端登錄到 SQL Server 失敗。 |
21 |
EventLog |
指示已將事件記錄到 Windows 應用程序日志中。 |
22 |
ErrorLog |
指示已將錯誤事件記錄到 SQL Server 錯誤日志中。 |
23 |
Lock:Released |
指示已釋放某個資源(如頁)的鎖。 |
24 |
Lock:Acquired |
指示獲取了某個資源(如數據頁)的鎖。 |
25 |
Lock:Deadlock |
指示兩個并發事務由于試圖獲得對方事務擁有的資源的不兼容鎖而發生了相互死鎖。 |
26 |
Lock:Cancel |
指示已取消獲取資源鎖(例如,由于死鎖)。 |
27 |
Lock:Timeout |
指示由于其他事務持有所需資源的阻塞鎖而使對資源(例如頁)鎖的請求超時。 超時由 @@LOCK_TIMEOUT 函數確定,并可用 SET LOCK_TIMEOUT 語句設置。 |
28 |
Degree of Parallelism Event(7.0 插入) |
在執行 SELECT、INSERT 或 UPDATE 語句之前發生。 |
33 |
Exception |
指示 SQL Server 中出現了異常。 |
34 |
SP:CacheMiss |
指示未在過程緩存中找到某個存儲過程。 |
35 |
SP:CacheInsert |
指示某個項被插入到過程緩存中。 |
36 |
SP:CacheRemove |
指示從過程緩存中刪除了某個項。 |
37 |
SP:Recompile |
指示已重新編譯存儲過程。 |
38 |
SP:CacheHit |
指示在過程緩存中找到了存儲過程。 |
40 |
SQL:StmtStarting |
在啟動了 Transact-SQL 語句時發生。 |
41 |
SQL:StmtCompleted |
在完成了 Transact-SQL 語句時發生。 |
42 |
SP:Starting |
指示啟動了存儲過程。 |
43 |
SP:Completed |
指示完成了存儲過程。 |
44 |
SP:StmtStarting |
指示已開始執行存儲過程中的 Transact-SQL 語句。 |
45 |
SP:StmtCompleted |
指示存儲過程中的 Transact-SQL 語句已執行完畢。 |
46 |
Object:Created |
指示 CREATE INDEX、CREATE TABLE 和 CREATE DATABASE 這樣的語句已創建了一個對象。 |
47 |
Object:Deleted |
指示已在 DROP INDEX 和 DROP TABLE 這樣的語句中刪除了對象。 |
50 |
SQL Transaction |
跟蹤 Transact-SQL BEGIN、COMMIT、SAVE 和 ROLLBACK TRANSACTION 語句。 |
51 |
Scan:Started |
指示啟動了表或索引掃描 |
52 |
Scan:Stopped |
指示停止了表或索引掃描。 |
53 |
CursorOpen |
指示 ODBC、OLE DB 或 DB-Library 在 Transact-SQL 語句中打開了一個游標。 |
54 |
TransactionLog |
將事務寫入事務日志時進行跟蹤。 |
55 |
Hash Warning |
指示未在緩沖分區進行的某一哈希操作(例如,哈希聯接、哈希聚合、哈希 union 運算、哈希非重復)已恢復為替換計劃。 發生此事件的原因可能是遞歸深度、數據扭曲、跟蹤標記或位計數。 |
58 |
Auto Stats |
指示發生了自動更新索引統計信息。 |
59 |
Lock:Deadlock Chain |
為導致死鎖的每個事件而生成。 |
60 |
Lock:Escalation |
指示較細粒度的鎖轉換成了較粗粒度的鎖(例如,頁鎖升級或轉換為 TABLE 或 HoBT 鎖)。 |
61 |
OLE DB Errors |
指示發生了 OLE DB 錯誤。 |
67 |
Execution Warnings |
指示在執行 SQL Server 語句或存儲過程期間發生的任何警告。 |
68 |
Showplan Text (Unencoded) |
顯示所執行 Transact-SQL 語句的計劃樹。 |
69 |
Sort Warnings |
指示不適合內存的排序操作。 不包括與創建索引有關的排序操作;只包括某查詢內的排序操作(如 SELECT 語句中使用的 ORDER BY 子句)。 |
70 |
CursorPrepare |
指示已準備了 ODBC、OLE DB 或 DB-Library 用于 Transact-SQL 語句的游標。 |
71 |
Prepare SQL |
ODBC、OLE DB 或 DB-Library 已準備好了一個或多個要使用的 Transact-SQL 語句。 |
72 |
Exec Prepared SQL |
ODBC、OLE DB 或 DB-Library 已執行了一個或多個準備好的 Transact-SQL 語句。 |
73 |
Unprepare SQL |
ODBC、OLE DB 或 DB-Library 已撤消(刪除)了一個或多個準備好的 Transact-SQL 語句。 |
74 |
CursorExecute |
執行了先前由 ODBC、OLE DB 或 DB-Library 為 Transact-SQL 語句準備的游標。 |
75 |
CursorRecompile |
由 ODBC 或 DB-Library 為 Transact-SQL 語句打開的游標已直接重新編譯或由于架構更改而重新編譯。 為 ANSI 和非 ANSI 游標觸發。 |
76 |
CursorImplicitConversion |
SQL Server 將 Transact-SQL 語句的游標從一種類型轉換為另一種類型。 為 ANSI 和非 ANSI 游標觸發。 |
77 |
CursorUnprepare |
ODBC、OLE DB 或 DB-Library 撤消(刪除)了準備好的 Transact-SQL 語句的游標。 |
78 |
CursorClose |
關閉了先前由 ODBC、OLE DB 或 DB-Library 為 Transact-SQL 語句打開的游標。 |
79 |
Missing Column Statistics |
可能曾經對優化器有用的列統計信息不可用。 |
80 |
Missing Join Predicate |
正在執行沒有聯接謂詞的查詢。 這可能導致長時間運行查詢。 |
81 |
Server Memory Change |
SQL Server 內存的使用量已增加或減少了 1 MB 或最大服務器內存的 5%(兩者中較大者)。 |
82-91 |
User Configurable (0-9) |
用戶定義的事件數據。 |
92 |
Data File Auto Grow |
指示服務器已自動擴展了數據文件。 |
93 |
Log File Auto Grow |
指示服務器已自動擴展了日志文件。 |
94 |
Data File Auto Shrink |
指示服務器已自動收縮了數據文件。 |
95 |
Log File Auto Shrink |
指示服務器已自動收縮了日志文件。 |
96 |
Showplan Text |
顯示來自查詢優化器的 SQL 語句的查詢計劃樹。 請注意,TextData 列不包含此事件的顯示計劃。 |
97 |
Showplan All |
顯示查詢計劃,并顯示已執行的 SQL 語句的完整編譯時詳細信息。 請注意,TextData 列不包含此事件的顯示計劃。 |
98 |
Showplan Statistics Profile |
顯示查詢計劃,并顯示已執行的 SQL 語句的完整運行時詳細信息。 請注意,TextData 列不包含此事件的顯示計劃。 |
100 |
RPC Output Parameter |
生成每個 RPC 的參數的輸出值。 |
108 |
Audit Add Login to Server Role Event |
在從固定服務器角色添加或刪除登錄時發生;針對 sp_addsrvrolemember 和 sp_dropsrvrolemember。 |
112 |
Audit App Role Change Password Event |
在更改應用程序角色的密碼時發生。 |
113 |
Audit Statement Permission Event |
在使用語句權限(如 CREATE TABLE)時發生。 |
114 |
Audit Schema Object Access Event |
在成功或未成功使用了對象權限(如 SELECT)時發生。 |
115 |
Audit Backup/Restore Event |
在發出 BACKUP 或 RESTORE 命令時發生。 |
116 |
Audit DBCC Event |
在發出 DBCC 命令時發生。 |
117 |
Audit Change Audit Event |
在修改審核跟蹤時發生。 |
118 |
Audit Object Derived Permission Event |
在發出 CREATE、ALTER 和 DROP 對象命令時發生。 |
119 |
OLEDB Call Event |
為分布式查詢和遠程存儲過程調用 OLE DB 訪問接口時發生。 |
120 |
OLEDB QueryInterface Event |
為分布式查詢和遠程存儲過程調用 OLE DB QueryInterface 時發生。 |
121 |
OLEDB DataRead Event |
對 OLE DB 訪問接口調用數據請求時發生。 |
122 |
Showplan XML |
在執行 SQL 語句時發生。 包括該事件可以標識 Showplan 運算符。 每個事件都存儲在格式正確的 XML 文檔中。 請注意,此事件的 Binary 列包含已編碼的顯示計劃。 使用 SQL Server Profiler 可打開跟蹤并查看顯示計劃。 |
123 |
SQL:FullTextQuery |
執行全文查詢時發生。 |
124 |
Broker:Conversation |
報告 Service Broker 會話的進度。 |
125 |
Deprecation Announcement |
使用將從 SQL Server 的未來版本中刪除的功能時發生。 |
126 |
Deprecation Final Support |
使用將從 SQL Server 的下一個主版本中刪除的功能時發生。 |
127 |
Exchange Spill Event |
在 tempdb 數據庫臨時寫入并行查詢計劃中的通信緩沖區時發生。 |
128 |
Audit Database Management Event |
創建、更改或刪除數據庫時發生。 |
129 |
Audit Database Object Management Event |
對數據庫對象(如架構)執行 CREATE、ALTER 或 DROP 語句時發生。 |
130 |
Audit Database Principal Management Event |
創建、更改或刪除數據庫的主體(如用戶)時發生。 |
131 |
Audit Schema Object Management Event |
創建、更改或刪除服務器對象時發生。 |
132 |
Audit Server Principal Impersonation Event |
服務器范圍中發生模擬(如 EXECUTE AS LOGIN)時發生。 |
133 |
Audit Database Principal Impersonation Event |
數據庫范圍中發生模擬(如 EXECUTE AS USER 或 SETUSER)時發生。 |
134 |
Audit Server Object Take Ownership Event |
服務器范圍中的對象的所有者發生更改時發生。 |
135 |
Audit Database Object Take Ownership Event |
數據庫范圍中的對象的所有者發生更改時發生。 |
136 |
Broker:Conversation Group |
Service Broker 創建新的會話組或刪除現有會話組時發生。 |
137 |
Blocked Process Report |
進程被阻塞的時間超過了指定的時間時發生。 不包括系統進程或正在等待未發現死鎖的資源的進程。 請使用 sp_configure 來配置生成報表時的閾值和頻率。 |
138 |
Broker:Connection |
報告 Service Broker 管理的傳輸連接的狀態。 |
139 |
Broker:Forwarded Message Sent |
Service Broker 轉發消息時發生。 |
140 |
Broker:Forwarded Message Dropped |
Service Broker 刪除用于轉發的消息時發生。 |
141 |
Broker:Message Classify |
Service Broker 確定消息的路由時發生。 |
142 |
Broker:Transmission |
指示在 Service Broker 傳輸層中發生了錯誤。 錯誤號和狀態值指示了錯誤源。 |
143 |
Broker:Queue Disabled |
指示檢測到有害消息,這是由于在 Service Broker 隊列中有五個連續的事務回滾。 該事件包含數據庫 ID 和包含有害消息的隊列的隊列 ID。 |
146 |
Showplan XML Statistics Profile |
在執行 SQL 語句時發生。 標識 Showplan 運算符,并顯示完整的編譯時數據。 請注意,此事件的 Binary 列包含已編碼的顯示計劃。 使用 SQL Server Profiler 可打開跟蹤并查看顯示計劃。 |
148 |
Deadlock Graph |
取消獲取鎖的嘗試時發生,這是因為該嘗試是死鎖的一部分,并且被選為死鎖犧牲品。 提供死鎖的 XML 說明。 |
149 |
Broker:Remote Message Acknowledgement |
Service Broker 發送或收到消息確認時發生。 |
150 |
Trace File Close |
跟蹤文件在回滾期間關閉時發生。 |
152 |
Audit Change Database Owner |
使用 ALTER AUTHORIZATION 更改數據庫的所有者,并且檢查執行該操作的權限時發生。 |
153 |
Audit Schema Object Take Ownership Event |
使用 ALTER AUTHORIZATION 來將所有者分配給對象,并且檢查執行該操作的權限時發生。 |
155 |
FT:Crawl Started |
全文爬網(填充)開始時發生。 用于檢查工作線程任務是否拾取了爬網請求。 |
156 |
FT:Crawl Stopped |
全文爬網(填充)停止時發生。 爬網成功完成或發生錯誤時停止。 |
157 |
FT:Crawl Aborted |
在全文爬網過程中遇到異常時發生。 通常導致全文爬網停止。 |
158 |
Audit Broker Conversation |
報告與 Service Broker 對話安全性相關的審核消息。 |
159 |
Audit Broker Login |
報告與 Service Broker 傳輸安全性相關的審核消息。 |
160 |
Broker:Message Undeliverable |
Service Broker 無法保留收到的消息時發生,該消息應當已傳遞給某個服務。 |
161 |
Broker:Corrupted Message |
Service Broker 收到損壞的消息時發生。 |
162 |
User Error Message |
顯示出現錯誤或異常時用戶看到的錯誤消息。 |
163 |
Broker:Activation |
隊列監視器啟動激活存儲過程時,發送 QUEUE_ACTIVATION 通知時,或者隊列監視器啟動的激活存儲過程退出時發生。 |
164 |
Object:Altered |
數據庫對象更改時發生。 |
165 |
Performance statistics |
將經過編譯的查詢計劃第一次緩存、重新編譯或從計劃緩存中刪除時發生。 |
166 |
SQL:StmtRecompile |
發生語句級別的重新編譯時發生。 |
167 |
Database Mirroring State Change |
鏡像數據庫的狀態更改時發生。 |
168 |
Showplan XML For Query Compile |
編譯 SQL 語句時發生。 顯示完整的編譯時數據。 請注意,此事件的 Binary 列包含已編碼的顯示計劃。 使用 SQL Server Profiler 可打開跟蹤并查看顯示計劃。 |
169 |
Showplan All For Query Compile |
編譯 SQL 語句時發生。 顯示完整的編譯時數據。 用于標識 Showplan 運算符。 |
170 |
Audit Server Scope GDR Event |
指示在服務器范圍中發生了權限的授予、拒絕或撤消事件(如創建登錄)。 |
171 |
Audit Server Object GDR Event |
指示發生了對架構對象(如表或函數)的授予、拒絕或撤消事件。 |
172 |
Audit Database Object GDR Event |
指示發生了對數據庫對象(如程序集和架構)的授予、拒絕或撤消事件。 |
173 |
Audit Server Operation Event |
使用了安全審核操作(如使用了更改設置、資源、外部訪問或授權)時發生。 |
175 |
Audit Server Alter Trace Event |
檢查語句的 ALTER TRACE 權限時發生。 |
176 |
Audit Server Object Management Event |
創建、更改或刪除服務器對象時發生。 |
177 |
Audit Server Principal Management Event |
創建、更改或刪除了服務器主體時發生。 |
178 |
Audit Database Operation Event |
發生數據庫操作(如檢查或訂閱查詢通知)時發生。 |
180 |
Audit Database Object Access Event |
訪問數據庫對象(如架構)時發生。 |
181 |
TM: Begin Tran starting |
BEGIN TRANSACTION 請求開始時發生。 |
182 |
TM: Begin Tran completed |
BEGIN TRANSACTION 請求完成時發生。 |
183 |
TM: Promote Tran starting |
PROMOTE TRANSACTION 請求開始時發生。 |
184 |
TM: Promote Tran completed |
PROMOTE TRANSACTION 請求完成時發生。 |
185 |
TM: Commit Tran starting |
COMMIT TRANSACTION 請求開始時發生。 |
186 |
TM: Commit Tran completed |
COMMIT TRANSACTION 請求完成時發生。 |
187 |
TM: Rollback Tran starting |
ROLLBACK TRANSACTION 請求開始時發生。 |
188 |
TM: Rollback Tran completed |
ROLLBACK TRANSACTION 請求完成時發生。 |
189 |
Lock:Timeout (timeout > 0) |
對資源(如頁)的鎖請求超時時發生。 |
190 |
Progress Report: Online Index Operation |
報告生成進程正在運行時,聯機索引生成操作的進度。 |
191 |
TM: Save Tran starting |
SAVE TRANSACTION 請求開始時發生。 |
192 |
TM: Save Tran completed |
SAVE TRANSACTION 請求完成時發生。 |
193 |
Background Job Error |
后臺作業不正常終止時發生。 |
194 |
OLEDB Provider Information |
分布式查詢運行并收集對應于提供程序連接的信息時發生。 |
195 |
Mount Tape |
收到磁帶裝入請求時發生。 |
196 |
Assembly Load |
發生加載 CLR 程序集的請求時發生。 |
198 |
XQuery Static Type |
執行 XQuery 表達式時發生。 此事件類提供靜態類型的 XQuery 表達式。 |
199 |
QN: subscription |
無法訂閱查詢注冊時發生。 TextData 列包含事件的有關信息。 |
200 |
QN: parameter table |
有關活動訂閱的信息存儲在內部參數表中。 在創建或刪除參數表時發生該事件類。 通常,重新啟動數據庫時將創建或刪除這些表。 TextData 列包含事件的有關信息。 |
201 |
QN: template |
查詢模板代表訂閱查詢的類。 通常,除參數值以外,相同類中的查詢是相同的。 當新的訂閱請求針對已存在的類 (Match)、新類 (Create) 或 Drop 類(指示清除沒有活動訂閱的查詢類的模板)時,發生此事件類。 TextData 列包含事件的有關信息。 |
202 |
QN: dynamics |
跟蹤查詢通知的內部活動。 TextData 列包含事件的有關信息。 |
213 |
Database Suspect Data Page |
指示何時將某頁添加到 msdb 的 suspect_pages 表。 |
214 |
CPU threshold exceeded |
指示資源調控器檢測到查詢超過 CPU 閾值 (REQUEST_MAX_CPU_TIME_SEC) 的時間。 |
215 |
指示 LOGON 觸發器或資源調控器分類器函數開始執行的時間。 |
指示 LOGON 觸發器或資源調控器分類器函數開始執行的時間。 |
216 |
PreConnect:Completed |
指示 LOGON 觸發器或資源調控器分類器函數完成執行的時間。 |
217 |
Plan Guide Successful |
指示 SQL Server 已成功為計劃指南中包含的查詢或批處理生成執行計劃。 |
218 |
Plan Guide Unsuccessful |
指示 SQL Server 無法為包含計劃指南的查詢或批處理生成執行計劃。 SQL Server 嘗試在不應用計劃指南的情況下為此查詢或批處理生成執行計劃。 無效的計劃指南可能是導致此問題的原因。 您可以通過使用 sys.fn_validate_plan_guide 系統函數驗證該計劃指南。 |
上述的跟蹤事件中,基本包含了SQL Server中所能做的任何操作,我們可以根據自己需要進行定義,當我們可以針對日常經常遇到的一些問題進行定位,比如:死鎖、等待、登錄失敗等等吧...當然也可以追蹤某個人的所有行為,這里我們來定義幾個來看看
我們定義追蹤所有語句批量操作的追蹤,從上面表我們可以查找到為12,13
exec sp_trace_setevent 2,12,1,1 exec sp_trace_setevent 2,13,1,1
通過如下存儲過程,將我們自定的追蹤啟動
--設置跟蹤狀態以啟動 exec sp_trace_setstatus @TraceID,1
至此,我們新建的追蹤已經開始運行了,我們可以利用上面的方法,來查看我們生成的追蹤文件了,其實大部分時候,我們都是利用此種方法設置好”圈套“,等待魚兒上網
比如死鎖查找,CPU消耗高,IO值高的那些語句....
我們可以利用如下語句,查找跟蹤文件的信息
--查看跟蹤文件以表顯示 select * from ::fn_trace_gettable('F:\SQLTest\.trc',1)
將我們剛才的所有操作,已經追蹤出來了。
通過如下命令進行跟蹤的關閉
--設置跟蹤狀態以停止 exec sp_trace_setstatus @TraceID,0
通過如下命令進行跟蹤的刪除
--從系統中移除跟蹤 exec sp_trace_setstatus @TraceID,2
我們知道在SQL Server默認的跟蹤文件在實例重啟時候,都會消失,所以我們可以通過如下方法解決,保證在每次實例重新啟動的時候都會執行該追蹤
--新建追蹤的存儲過程 use master go create proc StartBlackBoxTrace as begin --默認開啟追蹤所有的SQL 執行語句,文件文件路徑為默認 DECLARE @TraceID int DECLARE @MaxFileSize bigint SET @MaxFileSize=25 EXEC SP_TRACE_CREATE @TraceID OUTPUT, 8, NULL, @MaxFileSize EXEC SP_TRACE_SETSTATUS @TraceID,1 END --將該存儲過程設置為SQL Server服務啟動時自動啟動 EXEC sp_procoption 'StartBlackBoxTrace','STARTUP','ON' GO
通過如下腳本刪除到所有的跟蹤
create proc [dbo].[Performance_Trace_StopAll] AS declare traceCursor cursor for select id from sys.traces where id <> 1 open traceCursor declare @curid int fetch next from traceCursor into @curid while(@@fetch_status=0) begin exec sp_trace_setstatus @curid,0 exec sp_trace_setstatus @curid,2 fetch next from traceCursor into @curid end close traceCursor deallocate traceCursor
三.死鎖案例(2014年11月23日晚補充)
這里我們來利用自己新建跟蹤來跟蹤一個死鎖的發生過程,并且將其記錄到我們的Trace文件中,這里我們來制作一個死鎖
以上代碼參照院子里大牛宋沄劍,這里我們利用系統的自帶的profile進行設計追蹤,我們直接選擇系統自帶的死鎖模板,進行追蹤
然后設置,默認的SPID為大于等于50,小于50的為系統自有事件
然后,我們利用上面的死鎖腳本,運行獲取死鎖的捕捉
可以看到,我們已經順利的追蹤到這個死鎖。我們知道這種追蹤是高成本的,并且我們有時候不知道死鎖發生的具體時間,所以不能一直開著這個Profile,出于性能考慮也不建議這么做,所以我們采用新建的Trace文件,來保存改腳本,然后重定向到我們自己的文件夾,將死鎖的信息放置到該文件夾下,提供更大靈活性。
SQL Server本身自帶的Profile工具就提供編輯腳本的功能,我們將上面的設計,導出成Trace腳本,我們點擊“文件”,導出該設計腳本
將該腳本保存到一個位置,然后我們打開,我順便將默認的文件路徑添加上
/****************************************************/ /* Created by: SQL Server 2008 Profiler */ /* Date: 2014/11/23 20:28:11 */ /****************************************************/ -- Create a Queue declare @rc int declare @TraceID int declare @maxfilesize bigint --可以更改文件大小 set @maxfilesize = 5 --默認死鎖文件放置目錄 declare @FilePath nvarchar(max) set @FilePath=N'F:\SQLTest\DeadLock.trc' -- Please replace the text InsertFileNameHere, with an appropriate -- filename prefixed by a path, e.g., c:\MyFolder\MyTrace. The .trc extension -- will be appended to the filename automatically. If you are writing from -- remote server to local drive, please use UNC path and make sure server has -- write access to your network share exec @rc = sp_trace_create @TraceID output, 0, @FilePath, @maxfilesize, NULL if (@rc != 0) goto error -- Client side File and Table cannot be scripted -- Set the events declare @on bit set @on = 1 exec sp_trace_setevent @TraceID, 137, 15, @on exec sp_trace_setevent @TraceID, 137, 32, @on exec sp_trace_setevent @TraceID, 137, 1, @on exec sp_trace_setevent @TraceID, 137, 13, @on exec sp_trace_setevent @TraceID, 137, 22, @on exec sp_trace_setevent @TraceID, 148, 11, @on exec sp_trace_setevent @TraceID, 148, 12, @on exec sp_trace_setevent @TraceID, 148, 14, @on exec sp_trace_setevent @TraceID, 148, 1, @on exec sp_trace_setevent @TraceID, 26, 15, @on exec sp_trace_setevent @TraceID, 26, 32, @on exec sp_trace_setevent @TraceID, 26, 1, @on exec sp_trace_setevent @TraceID, 26, 9, @on exec sp_trace_setevent @TraceID, 26, 57, @on exec sp_trace_setevent @TraceID, 26, 2, @on exec sp_trace_setevent @TraceID, 26, 10, @on exec sp_trace_setevent @TraceID, 26, 11, @on exec sp_trace_setevent @TraceID, 26, 35, @on exec sp_trace_setevent @TraceID, 26, 12, @on exec sp_trace_setevent @TraceID, 26, 13, @on exec sp_trace_setevent @TraceID, 26, 6, @on exec sp_trace_setevent @TraceID, 26, 14, @on exec sp_trace_setevent @TraceID, 26, 22, @on exec sp_trace_setevent @TraceID, 25, 15, @on exec sp_trace_setevent @TraceID, 25, 32, @on exec sp_trace_setevent @TraceID, 25, 1, @on exec sp_trace_setevent @TraceID, 25, 9, @on exec sp_trace_setevent @TraceID, 25, 57, @on exec sp_trace_setevent @TraceID, 25, 2, @on exec sp_trace_setevent @TraceID, 25, 10, @on exec sp_trace_setevent @TraceID, 25, 11, @on exec sp_trace_setevent @TraceID, 25, 35, @on exec sp_trace_setevent @TraceID, 25, 12, @on exec sp_trace_setevent @TraceID, 25, 13, @on exec sp_trace_setevent @TraceID, 25, 6, @on exec sp_trace_setevent @TraceID, 25, 14, @on exec sp_trace_setevent @TraceID, 25, 22, @on exec sp_trace_setevent @TraceID, 59, 32, @on exec sp_trace_setevent @TraceID, 59, 1, @on exec sp_trace_setevent @TraceID, 59, 57, @on exec sp_trace_setevent @TraceID, 59, 2, @on exec sp_trace_setevent @TraceID, 59, 14, @on exec sp_trace_setevent @TraceID, 59, 22, @on exec sp_trace_setevent @TraceID, 59, 35, @on exec sp_trace_setevent @TraceID, 59, 12, @on exec sp_trace_setevent @TraceID, 60, 32, @on exec sp_trace_setevent @TraceID, 60, 9, @on exec sp_trace_setevent @TraceID, 60, 57, @on exec sp_trace_setevent @TraceID, 60, 10, @on exec sp_trace_setevent @TraceID, 60, 11, @on exec sp_trace_setevent @TraceID, 60, 35, @on exec sp_trace_setevent @TraceID, 60, 12, @on exec sp_trace_setevent @TraceID, 60, 6, @on exec sp_trace_setevent @TraceID, 60, 14, @on exec sp_trace_setevent @TraceID, 60, 22, @on exec sp_trace_setevent @TraceID, 189, 15, @on exec sp_trace_setevent @TraceID, 189, 32, @on exec sp_trace_setevent @TraceID, 189, 1, @on exec sp_trace_setevent @TraceID, 189, 9, @on exec sp_trace_setevent @TraceID, 189, 57, @on exec sp_trace_setevent @TraceID, 189, 2, @on exec sp_trace_setevent @TraceID, 189, 10, @on exec sp_trace_setevent @TraceID, 189, 11, @on exec sp_trace_setevent @TraceID, 189, 35, @on exec sp_trace_setevent @TraceID, 189, 12, @on exec sp_trace_setevent @TraceID, 189, 13, @on exec sp_trace_setevent @TraceID, 189, 6, @on exec sp_trace_setevent @TraceID, 189, 14, @on exec sp_trace_setevent @TraceID, 189, 22, @on exec sp_trace_setevent @TraceID, 45, 16, @on exec sp_trace_setevent @TraceID, 45, 1, @on exec sp_trace_setevent @TraceID, 45, 9, @on exec sp_trace_setevent @TraceID, 45, 17, @on exec sp_trace_setevent @TraceID, 45, 10, @on exec sp_trace_setevent @TraceID, 45, 18, @on exec sp_trace_setevent @TraceID, 45, 11, @on exec sp_trace_setevent @TraceID, 45, 35, @on exec sp_trace_setevent @TraceID, 45, 12, @on exec sp_trace_setevent @TraceID, 45, 13, @on exec sp_trace_setevent @TraceID, 45, 6, @on exec sp_trace_setevent @TraceID, 45, 14, @on exec sp_trace_setevent @TraceID, 45, 22, @on exec sp_trace_setevent @TraceID, 45, 15, @on exec sp_trace_setevent @TraceID, 44, 1, @on exec sp_trace_setevent @TraceID, 44, 9, @on exec sp_trace_setevent @TraceID, 44, 10, @on exec sp_trace_setevent @TraceID, 44, 11, @on exec sp_trace_setevent @TraceID, 44, 35, @on exec sp_trace_setevent @TraceID, 44, 12, @on exec sp_trace_setevent @TraceID, 44, 6, @on exec sp_trace_setevent @TraceID, 44, 14, @on exec sp_trace_setevent @TraceID, 44, 22, @on exec sp_trace_setevent @TraceID, 41, 15, @on exec sp_trace_setevent @TraceID, 41, 16, @on exec sp_trace_setevent @TraceID, 41, 1, @on exec sp_trace_setevent @TraceID, 41, 9, @on exec sp_trace_setevent @TraceID, 41, 17, @on exec sp_trace_setevent @TraceID, 41, 10, @on exec sp_trace_setevent @TraceID, 41, 18, @on exec sp_trace_setevent @TraceID, 41, 11, @on exec sp_trace_setevent @TraceID, 41, 35, @on exec sp_trace_setevent @TraceID, 41, 12, @on exec sp_trace_setevent @TraceID, 41, 13, @on exec sp_trace_setevent @TraceID, 41, 6, @on exec sp_trace_setevent @TraceID, 41, 14, @on exec sp_trace_setevent @TraceID, 40, 1, @on exec sp_trace_setevent @TraceID, 40, 9, @on exec sp_trace_setevent @TraceID, 40, 6, @on exec sp_trace_setevent @TraceID, 40, 10, @on exec sp_trace_setevent @TraceID, 40, 14, @on exec sp_trace_setevent @TraceID, 40, 11, @on exec sp_trace_setevent @TraceID, 40, 35, @on exec sp_trace_setevent @TraceID, 40, 12, @on -- Set the Filters declare @intfilter int declare @bigintfilter bigint exec sp_trace_setfilter @TraceID, 10, 0, 7, N'SQL Server Profiler - efbc9d24-69cd-465f-8daf-e38493da0332' -- Set the trace status to start exec sp_trace_setstatus @TraceID, 1 -- display trace id for future references select TraceID=@TraceID goto finish error: select ErrorCode=@rc finish: go
我們只需要將這個腳本運行就可以,當然此段腳本,在實例重啟的時候,所有的trace都會刪除掉,可以將該段代碼改成存儲過程,然后設置成實例啟動的時候運行,
方法參考本篇的上半部分。
當然我們也可以設置別的參數,比如啟動時間,運行時間,跟蹤文件大小,位置,數量等,刪除不必要的trace跟蹤事件...
當運行到一段時間之后,我們直接拷貝下來,找臺電腦分析就可以了。
更靈活的方式是采取非業務高峰期,利用SQL Server自帶的郵件提醒功能,直接檢測出問題,然后Send Email....
四.SQL Server中黑匣子(2014年11月28日晚補充)
黑匣子作為飛機出現事故后的追蹤利器,在微軟的SQL Server這個數據庫中默認也給裝上了此引擎,但是沒有開啟,此功能可能幫助我們診斷間歇性的服務器崩潰。它比我們上面介紹的默認開啟的跟蹤跟蹤的信息更全,跟蹤更大一些。其內容包含了:“SP:啟動”、“SQL:批處理啟動”、異常和注意等事件
這個跟蹤通過在sp_trace_create的默認@option參數設置為8來配置的。代碼如下:
DECLARE @Traced INT EXEC sp_trace_create @Traced OUTPUT, @options=8 EXEC sp_trace_setstatus @Traced,1
通過以上的配置會自動配置成兩個滾動文件,當達到默認的最大文件容量5MB的時候,就在兩個文件中循環滾動依次更新。
當然如果感覺生成的文件5MB有點小,可以手動配置更改大小,或者自定義文件路徑,這些都是允許自定義設置的。
DECLARE @TraceID INT DECLARE @maxfilesize BIGINT SET @maxfilesize=25 DECLARE @tracefile nvarchar(245) SET @tracefile=N'F:\SQLTest\TRACE\MYTRACE.trc' EXEC sp_trace_create @TraceID OUTPUT, @options=8, @tracefile=NULL, @maxfilesize=@maxfilesize EXEC sp_trace_setstatus @TraceID,1
此方法能將數據庫執行的所有SQL滾動記錄下來,以防止SQL Server宕機之后的事故查找。
參考我博文的上面介紹,只需要將這個方法存儲于存儲過程,然后設置成實例啟動后運行,那么恭喜你的SQL Server已經成功裝上了黑匣子引擎,假如有一天突然宕機,我們只需要打開此黑匣子就可以。
結語
參考文獻有下面
SQL Server 默認跟蹤(Default Trace)
SQL Server 2005 - Default Trace (默認跟蹤)
文章列表