一. 從數據庫連接情況來判斷異常:
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