mssql資料庫系統日常維護關鍵資訊提取
效能檢視(SQLServer05以上版本)來排查系統異常的基本方法,希望能對大家有所幫助。
這裡分兩部分來介紹:
一. 從資料庫連線情況來判斷異常:
1. 首先我們來看一下目前資料庫系統所有請求情況:
--request infoselect s.session_id, s.status,db_name(r.database_id) as database_name, s.login_name,s.login_time, s.host_name, c.client_net_address,c.client_tcp_port,s.program_name, r.cpu_time, r.reads, r.writes,c.num_reads,c.num_writes, s.client_interface_name, s.last_request_start_time, s.last_request_end_time, c.connect_time, c.net_transport, c.net_packet_size, r.start_time, r.status, r.command, r.blocking_session_id, r.wait_type, r.wait_time, r.last_wait_type, r.wait_resource, r.open_transaction_count, r.percent_complete,r.granted_query_memory fromSys.dm_exec_requests r with(nolock) right outer join Sys.dm_exec_sessions s with(nolock) on r.session_id = s.session_id right outer join Sys.dm_exec_connections c with(nolock) on s.session_id = c.session_id where s.session_id >50 order by s.session_id
某臺生產機執行情況:
這個查詢將目前資料庫中的所有請求都顯示出來了,其中比較重要的有Status、Login_name、Host_Name,Client_Net_Address、Program_name
等,但是資訊比較多,我們很難檢視有什麼異常,但是可以通過一圖中紅色圈的數字:441 初步判斷連線數是否超過了平時的標準(很多時候系統異常是連線
數過多造成的,而連線數過多又是因為其他原因影響的)。
2. 哪個使用者連線數最多:
--request info by userselect login_name,COUNT(0) user_count from Sys.dm_exec_requests r with(nolock) right outer join Sys.dm_exec_sessions s with(nolock) on r.session_id = s.session_id rightouter join Sys.dm_exec_connections c with(nolock) on s.session_id = c.session_id where s.session_id >50 group by login_name order by 2 desc
執行結果:
從圖中我們可以很方便的看出使用者連線數情況,如果我們的不同的功能是使用不同的的資料庫賬號的話,就能初步判斷是哪部分功能可能出現了異常。
3. 哪臺機器發起到資料庫的連線數最多:
--request info by hostnameselect s.host_name,c.client_net_address,COUNT(0) host_count from Sys.dm_exec_requests r with(nolock) right outer join Sys.dm_exec_sessions s with(nolock) on r.session_id = s.session_id right outer join Sys.dm_exec_connections c with(nolock) on s.session_id = c.session_id where s.session_id >50 group by host_name,client_net_address order by 3 desc
執行結果:
這個查詢能夠一下就幫我們找出來哪些機器發起了對資料庫的連結,它們的連結數量是否有異常;這個其實對調查某些問題非常有用,我有一次就遇
到一個case:
使用者反映,過一兩個星期,系統就會出現一次異常,出問題時資料庫連線數量很高,大量的訪問被資料庫拒絕,過半個小時左右,系統又自動恢復了,但是
在資料庫裡面檢視,並沒有發現有異常的程序和錯誤的資訊,問題一時很棘手,很難定位,系統不穩定領導不滿,DBA頂著壓力一時不知道如何是好;後面
轉換方向,通過調查問題發生時,為什麼會產生這麼多連線,這些連線是那些機器發過來的,這些連線發過來正常嗎,是資料庫不砍業務的重負,還是業務
在某個時間段內會出現暴漲等一系列原因,最終找出是一臺Web因為開發人員程式碼寫的有問題,記憶體出現記憶體洩露,導致大量的連線不能釋放,出問題是,
發出的資料庫連線數比平時高3-4倍,最終影響到了資料庫,問題壓根和資料庫沒關係(從這個事實看出,DBA真是的炮灰角色,不是自己的問題,也得頂
著壓力調查出原因呀);如果在類似問題發生時,我們能通過這個查詢及早知道問題是出在某臺Web機器上,那就不用費盡心力來調查資料庫了。
4. 這些連線在訪問哪個庫:
--request info by databasesselect db_name(r.database_id) as database_name,COUNT(0) host_count from Sys.dm_exec_requests r with(nolock) right outer join Sys.dm_exec_sessions s with(nolock) on r.session_id = s.session_id right outer join Sys.dm_exec_connections c with(nolock) on s.session_id = c.session_id where s.session_id >50 group by r.database_id order by 2 desc
結果(為NULL的估計是沒辦法定位庫):
5. 程序狀態:
--request info by statusselect s.status,COUNT(0) host_count from Sys.dm_exec_requests r with(nolock) right outer join Sys.dm_exec_sessions s with(nolock) on r.session_id = s.session_id right outer join Sys.dm_exec_connections c with(nolock) on s.session_id = c.session_id where s.session_id >50 group by s.status order by 2 desc
結果(running數比較多,表面資料庫壓力比較大):
二. 從阻塞情況來判斷異常(這部分內容不再一一貼圖,直接上指令碼):
1. 檢視資料庫阻塞情況:
----------------------------------------Blocked Info---------------------------------- --記錄當前阻塞資訊 select t1.resource_type as [lock type] ,db_name(resource_database_id) as [database] ,t1.resource_associated_entity_id as [blk object] ,t1.request_mode as [lock req] -- lock requested ,t1.request_session_id as [waiter sid] -- spid of waiter ,t2.wait_duration_ms as [wait time] ,(select text from sys.dm_exec_requests as r with(nolock) --- get sql for waiter cross apply sys.dm_exec_sql_text(r.sql_handle) where r.session_id = t1.request_session_id) as waiter_batch ,(select substring(qt.text,r.statement_start_offset/2, (case when r.statement_end_offset = -1 then len(convert(nvarchar(max), qt.text)) * 2 else r.statement_end_offset end - r.statement_start_offset)/2+1) from sys.dm_exec_requests as r with(nolock) cross apply sys.dm_exec_sql_text(r.sql_handle) as qt where r.session_id = t1.request_session_id) as waiter_stmt --- statement executing now ,t2.blocking_session_id as [blocker sid] --- spid of blocker ,(select text from sys.sysprocesses as p with(nolock) --- get sql for blocker cross apply sys.dm_exec_sql_text(p.sql_handle) where p.spid = t2.blocking_session_id) as blocker_stmt,getdate() time from sys.dm_tran_locks as t1 with(nolock) , sys.dm_os_waiting_tasks as t2 with(nolock) where t1.lock_owner_address = t2.resource_address
2. 檢視阻塞其他程序的程序(阻塞源頭):
--阻塞其他session的session select t2.blocking_session_id,COUNT(0) counts from sys.dm_tran_locks as t1 with(nolock) , sys.dm_os_waiting_tasks as t2 with(nolock) where t1.lock_owner_address = t2.resource_address group by blocking_session_id order by 2
3. 被阻塞時間最長的程序:
--被阻塞時間最長的sessionselect top 10 t1.resource_type as [lock type] ,db_name(resource_database_id) as [database] ,t1.resource_associated_entity_id as [blk object] ,t1.request_mode as [lock req] -- lock requested ,t1.request_session_id as [waiter sid] -- spid of waiter ,t2.wait_duration_ms as [wait time] ,(select text from sys.dm_exec_requests as r with(nolock) --- get sql for waiter cross apply sys.dm_exec_sql_text(r.sql_handle) where r.session_id = t1.request_session_id) as waiter_batch ,(select substring(qt.text,r.statement_start_offset/2, (case when r.statement_end_offset = -1 then len(convert(nvarchar(max), qt.text)) * 2 else r.statement_end_offset end - r.statement_start_offset)/2+1) from sys.dm_exec_requests as r with(nolock) cross apply sys.dm_exec_sql_text(r.sql_handle) as qt where r.session_id = t1.request_session_id) as waiter_stmt --- statement executing now ,t2.blocking_session_id as [blocker sid] --- spid of blocker ,(select text from sys.sysprocesses as p with(nolock) --- get sql for blocker cross apply sys.dm_exec_sql_text(p.sql_handle) where p.spid = t2.blocking_session_id) as blocker_stmt,getdate() time from sys.dm_tran_locks as t1 with(nolock) , sys.dm_os_waiting_tasks as t2 with(nolock) where t1.lock_owner_address = t2.resource_address order by t2.wait_duration_ms desc
此文大致總結了通過DMV調查資料庫異常的基本方法和步驟,如果大家在調查問題時能夠靈活運用,相信對資料庫異常情況的定位和解決能夠更快更有效。