數據庫系統異常排查之DMV(轉)

一.  從數據庫連接情況來判斷異常:

1. 首先我們來看一下目前數據庫系統所有請求情況:

select 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. 哪個用戶連接數最多:

select 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
從圖中我們可以很方便的看出用戶連接數情況,如果我們的不同的功能是使用不同的的數據庫賬號的話,就能初步判斷是哪部分功能可能出現

了異常。
select 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. 這些連接在訪問哪個庫:

select 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
5. 進程狀態:
select 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數比較多,表面數據庫壓力比較大):
二. 從阻塞情況來判斷異常

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] ,t1.request_session_id as [waiter sid],t2.wait_duration_ms as [wait time] ,(select

text from sys.dm_exec_requests as r with(nolock) 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 ,t2.blocking_session_id as [blocker sid] ,(select text from sys.sysprocesses as p with

(nolock) 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. 查看阻塞其他進程的進程(阻塞源頭):
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. 被阻塞時間最長的進程:

select 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],t1.request_session_id as [waiter sid],t2.wait_duration_ms as [wait time],

(select text from sys.dm_exec_requests as r with(nolock) 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 ,t2.blocking_session_id as [blocker sid],(select text from sys.sysprocesses as p with

(nolock) 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


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章