1. 程式人生 > >mssql資料庫系統日常維護關鍵資訊提取

mssql資料庫系統日常維護關鍵資訊提取

資料庫系統異常是DBA經常要面臨的情景,一名有一定從業經驗的DBA,都會有自己一套故障排查的方法和步驟,此文為為大家介紹一下通過系統

效能檢視(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
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 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
right
outer 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調查資料庫異常的基本方法和步驟,如果大家在調查問題時能夠靈活運用,相信對資料庫異常情況的定位和解決能夠更快更有效。