數據庫系統異常是DBA經常要面臨的情景,一名有一定從業經驗的DBA,都會有自己一套故障排查的方法和步驟,此文為為大家介紹一下通過系統
性能視圖(SQLServer05以上版本)來排查系統異常的基本方法,希望能對大家有所幫助。
【0】DMV監控
需要的權限
USE master; GO CREATE LOGIN [telegraf] WITH PASSWORD = N'mystrongpassword'; GO GRANT VIEW SERVER STATE TO [telegraf]; GO GRANT VIEW ANY DEFINITION TO [telegraf]; GO For Azure SQL Database, you require the View Database State permission and can create a user with a password directly in the database. CREATE USER [telegraf] WITH PASSWORD = N'mystrongpassword'; GO GRANT VIEW DATABASE STATE TO [telegraf]; GO
【0.1】基本版本
效果計數器:來自1000多個指標 sys.dm_os_performance_counters
-
等待統計:等待任務分類為
sys.dm_os_wait_stats
-
內存業務員:來自的內存故障
sys.dm_os_memory_clerks
-
數據庫大小:數據庫大小趨勢從
sys.dm_io_virtual_file_stats
-
數據庫IO:來自的數據庫I / O
sys.dm_io_virtual_file_stats
-
數據庫延遲:來自的數據庫延遲
sys.dm_io_virtual_file_stats
-
數據庫屬性:數據庫屬性,狀態和恢復模型,來自
sys.databases
-
操作系統容量:可用空間,已用空間和總空間
sys.dm_os_volume_stats
-
CPU:CPU使用率
sys.dm_os_ring_buffers
【0.2】更新版本
-
數據庫IO:來自的IO統計信息
sys.dm_io_virtual_file_stats
-
記憶文員:來自的記憶文員分類
sys.dm_os_memory_clerks
,大多數文員都給了一個友好的名字。 -
性能計數器:來自的性能計數器的選擇列表
sys.dm_os_performance_counters
。一些重要的指標包括:服務器屬性:處於所有可能狀態(聯機,脫機,可疑等)的數據庫數,cpu計數,物理內存,SQL Server服務正常運行時間和SQL Server版本。對於Azure SQL相關屬性,例如Tier,#Vcores,Memory等。- 活動:事務/秒/數據庫,批處理請求/秒,被阻止的進程,以及更多
- 可用性組:發送到副本的字節,從副本接收的字節,已接收的日志字節,日志發送隊列,事務延遲等
- 日志活動:日志字節/秒刷新,日志刷新/秒,日志刷新等待時間
- 內存:PLE,每秒頁面讀取,每秒頁面寫入等
- TempDB:可用空間,版本存儲使用率,活動臨時表,臨時表創建率等
- 資源調控器:每個工作負載組的CPU使用率,每秒請求數,已排隊請求數和已阻止任務等
-
等待統計信息:等待時間(以毫秒為單位),等待任務的數量,資源等待時間,信號等待時間,最大等待時間(以毫秒為單位),等待類型和等待類別。使用查詢存儲中使用的相同類別對等待進行分類。
-
計划程序 -捕獲 sys.dm_os_schedulers。
-
SqlRequests-捕獲 dm_exec_requests 和 dm_exec_sessions 的快照,使您可以運行請求以及等待類型和阻止會話。
-
VolumeSpace-使用 sys.dm_os_volume_stats 來獲取每個包含數據或日志文件的磁盤上的總空間,已使用空間和已占用空間。(請注意,即使啟用,它也不會從Azure SQL數據庫或SQL托管實例獲取任何數據)。高頻運行(即每10秒一次)是沒有意義的,但是不會造成任何問題。
-
CPU -使用緩沖環(sys.dm_os_ring_buffers)獲得CPU的數據,該表是每分鍾更新一次。(請注意,即使啟用,它也不會從Azure SQL數據庫或SQL托管實例獲取任何數據)。為了允許在每個語句的基礎上進行跟蹤,此查詢為每個查詢生成唯一的標記。根據數據庫的工作量,這可能會導致基數較高。有關管理系列基數的提示,請參考FAQ 。
可以直接使用以下指標,而無需進行增量計算:
- SQLServer:Buffer Manager \緩沖區高速緩存命中率
- SQLServer:緩沖區管理器\頁面預期壽命
- SQLServer:緩沖區節點\頁面壽命期望
- SQLServer:數據庫副本\日志應用暫掛隊列
- SQLServer:數據庫副本\日志應用就緒隊列
- SQLServer:數據庫副本\日志發送隊列
- SQLServer:數據庫副本\恢復隊列
- SQLServer:數據庫\數據文件的大小(KB)
- SQLServer:數據庫\日志文件的大小(KB)
- SQLServer:數據庫\日志文件使用的大小(KB)
- SQLServer:數據庫\使用的XTP內存(KB)
- SQLServer:常規統計信息\活動臨時表
- SQLServer:常規統計信息\進程已阻止
- SQLServer:General Statistics \ Temp表進行銷毀
- SQLServer:常規統計信息\用戶連接
- SQLServer:內存代理文員\內存代理文員大小
- SQLServer:內存管理器\內存授予待定
- SQLServer:內存管理器\目標服務器內存(KB)
- SQLServer:內存管理器\服務器總內存(KB)
- SQLServer:資源池統計信息\活動內存授予量(KB)
- SQLServer:資源池統計信息\磁盤讀取字節/秒
- SQLServer:資源池統計信息\磁盤讀取IO限制/秒
- SQLServer:資源池統計信息\磁盤讀取IO /秒
- SQLServer:資源池統計信息\磁盤寫字節數/秒
- SQLServer:資源池統計信息\磁盤寫IO限制/秒
- SQLServer:資源池統計信息\磁盤寫入IO /秒
- SQLServer:資源池統計信息\已用內存(KB)
- SQLServer:Transactions \ tempdb中的可用空間(KB)
- SQLServer:事務\版本存儲大小(KB)
- SQLServer:用戶可設置\查詢
- SQLServer:工作負載組統計信息\阻止的任務
- SQLServer:工作負載組統計信息\ CPU使用率%
- SQLServer:工作負載組統計信息\排隊的請求
- SQLServer:工作負載組統計\請求完成/秒
QLServer:Buffer Manager\Buffer cache hit ratio SQLServer:Buffer Manager\Page life expectancy SQLServer:Buffer Node\Page life expectancy SQLServer:Database Replica\Log Apply Pending Queue SQLServer:Database Replica\Log Apply Ready Queue SQLServer:Database Replica\Log Send Queue SQLServer:Database Replica\Recovery Queue SQLServer:Databases\Data File(s) Size (KB) SQLServer:Databases\Log File(s) Size (KB) SQLServer:Databases\Log File(s) Used Size (KB) SQLServer:Databases\XTP Memory Used (KB) SQLServer:General Statistics\Active Temp Tables SQLServer:General Statistics\Processes blocked SQLServer:General Statistics\Temp Tables For Destruction SQLServer:General Statistics\User Connections SQLServer:Memory Broker Clerks\Memory broker clerk size SQLServer:Memory Manager\Memory Grants Pending SQLServer:Memory Manager\Target Server Memory (KB) SQLServer:Memory Manager\Total Server Memory (KB) SQLServer:Resource Pool Stats\Active memory grant amount (KB) SQLServer:Resource Pool Stats\Disk Read Bytes/sec SQLServer:Resource Pool Stats\Disk Read IO Throttled/sec SQLServer:Resource Pool Stats\Disk Read IO/sec SQLServer:Resource Pool Stats\Disk Write Bytes/sec SQLServer:Resource Pool Stats\Disk Write IO Throttled/sec SQLServer:Resource Pool Stats\Disk Write IO/sec SQLServer:Resource Pool Stats\Used memory (KB) SQLServer:Transactions\Free Space in tempdb (KB) SQLServer:Transactions\Version Store Size (KB) SQLServer:User Settable\Query SQLServer:Workload Group Stats\Blocked tasks SQLServer:Workload Group Stats\CPU usage % SQLServer:Workload Group Stats\Queued requests SQLServer:Workload Group Stats\Requests completed/sec
【1】 從數據庫連接情況來判斷異常
【1.1】目前數據庫系統所有請求情況
--request info 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 初步判斷連接數是否超過了平時的標准(很多時候系統異常是連接
數過多造成的,而連接數過多又是因為其他原因影響的)。
【1.2】哪個用戶連接數最多
--request info by user 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
運行結果:
從圖中我們可以很方便的看出用戶連接數情況,如果我們的不同的功能是使用不同的的數據庫賬號的話,就能初步判斷是哪部分功能可能出現了異常。
【1.3】 哪台機器發起到數據庫的連接數最多
--request info by hostname 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機器上,那就不用費盡心力來調查數據庫了。
【1.4】 這些連接在訪問哪個庫
--request info by databases 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
結果(為NULL的估計是沒辦法定位庫):
【1.5】進程狀態
--request info by status 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數比較多,表面數據庫壓力比較大):
【2】 從阻塞情況來判斷異常
(這部分內容不再一一貼圖,直接上腳本):
【2.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.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
【2.3】被阻塞時間最長的進程
--被阻塞時間最長的session 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] -- 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
【3】核心dmv
select * from test.sys.dm_tran_locks --庫級別:查看該庫鎖情況 select * from master.sys.dm_os_performance_counters --實例級別:啟動后的累計性能計數器 select * from master.sys.dm_os_wait_stats --實例級別:查看當前所有等待統計 select * from master.sys.dm_os_waiting_tasks --實例級別:查看當前所有等待的進程任務情況 select * from master.sys.dm_exec_requests --實例級別:查看當前所有的請求信息 select * from master.sys.dm_exec_sessions --實例級別:查看當前所有的登陸會話信息 select * from master.sys.dm_exec_connections --實例級別:查看當前所有的連接信息 select * from master.sys.sysprocesses --實例級別:查看當前所有的連接進程 select * from master.sys.dm_exec_query_stats --實例級別:查看執行計划/緩存,以此可以查看過去一段時間的慢SQL cross apply sys.dm_exec_sql_text(sql_handle) --一般用這個函數來解析sql語句 exec sp_who --查看實例登陸情況系統sp exec sp_who2 'sa' --查看制定用戶登錄情況 exec sp_lock --查看實例鎖情況
參考:https://www.cnblogs.com/fygh/archive/2012/03/12/2391764.html