SQL Server服務器CPU爆高解決


     昨天下午,測試反映trunk測試環境的數據庫CPU一直100%,一開始以為是病毒,內網這段時間老是有個挖礦的病毒,查了一下被隔離了,但是數據庫還是慢,停掉SQL server的服務CPU降下來,啟動SSQL server的服務器就CPU就到100%,按照正常情況,

SQL Server導致CPU爆高,一般是異常SQL引起,但查詢了監控:

   

   查詢是RiskControlAnalysis,TaskTrunk庫的sql比較多,先分離RiskControlAnalysis看看是否是這個庫的原因,分離后CPU還是很高,再分離TaskTrunk庫,報錯,無法分離,這時懷疑是服務器的磁盤性能問題,停SQL服務,用

CrystalDiskMark 6.0測試一下磁盤的性能,磁盤性能的確不怎樣,但是也沒差到這樣的地步。

    后面只能進一步分離TaskTrunk庫,分離后,在看服務器CPU,發現正常了,原因就出在TaskTrunk庫,后來在看看監控的sql,發現一條查詢SQL:     

select count(1) from tb_log E where 1=1  and E.taskid=@taskid

 這個tb_log 有3億條,查詢taskid字段沒有索引,導致查詢IO很慢,進而影響CPU爆高。后重建一張新的tb_log表,並在taskid字段加上索引,以前的表做歷史數據。性能問題解決。

  

   現在想想,就一個簡單的SQL查詢,用DMV性能視圖和實時監控的SQL,為何查不出來,這個監控查SQL,他的CPU和時間都不是特別高,並沒有特殊異常的情況,而且查數據庫也沒有未提交的事務在運行。

  如果這樣的情況出現在線上,解決的時間這么長,肯定會問題。想想有沒有簡單的方法發現這個SQL,突發靈感,以前查詢正在執行的SQL就可以發現這個問題,測試了一下,的確可用:

    這個SQL:  查詢正在執行的SQL

                    優勢:  1,以前的DMV是查已經執行完畢的SQL,如果這個SQL一直假死,性能視圖就查不出來

                               2,和[sp_WhoIsActive]監控出來的sql相比,能很清晰的顯示正在執行的sql和等待事件,定位更精准,特別是正在運行的

 

--數據庫CPU很高,查詢問題的SQL,根據時間“等待毫秒”,查出問題的SQL
SELECT   spid,
         blocked,
         DB_NAME(sp.dbid) AS DBName,
(select top 1 s.host_process_id
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.host_name=sp.hostname) 應用服務器進程Id,
(select top 1 c.client_net_address
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.host_name=sp.hostname) IP,
         a.[Text] AS [TextData],
         waitresource,
         sp.waittime 等待毫秒,
         sp.stmt_start,
         lastwaittype,
          sp.hostname,
         a.[Text] AS [TextData],
          program_name,
          sp.loginame,
         sp.Status,
         SUBSTRING(A.text, sp.stmt_start / 2,
         (CASE WHEN sp.stmt_end = -1 THEN DATALENGTH(A.text) ELSE sp.stmt_end
         END - sp.stmt_start) / 2) AS [current_cmd]
FROM     sys.sysprocesses AS sp OUTER APPLY sys.dm_exec_sql_text (sp.sql_handle) AS A
WHERE    spid > 50 --and lastwaittype='HADR_SYNC_COMMIT'
AND Status<>'sleeping'                     
ORDER BY sp.waittime desc;
View Code

 

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM