SQL Server伺服器CPU爆高解決

zping發表於2019-02-19

     昨天下午,測試反映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 ,
        waitresource ,
        sp.waittime 等待毫秒 ,
        sp.stmt_start ,
        lastwaittype ,
        sp.hostname ,
        ( 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] ,
        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;

 

  

 

相關文章