RDS SQL Server CPU使用率高問(wèn)題排查
本文介紹RDS SQL Server使用過(guò)程中遇到的CPU使用率過(guò)高甚至達(dá)到100%時(shí),一些常見(jiàn)原因及解決方法。
阿里云提醒您:
如果您對(duì)實(shí)例或數(shù)據(jù)有修改、變更等風(fēng)險(xiǎn)操作,務(wù)必注意實(shí)例的容災(zāi)、容錯(cuò)能力,確保數(shù)據(jù)安全。
如果您對(duì)實(shí)例(包括但不限于ECS、RDS)等進(jìn)行配置與數(shù)據(jù)修改,建議提前創(chuàng)建快照或開(kāi)啟RDS日志備份等功能。
如果您在阿里云平臺(tái)授權(quán)或者提交過(guò)登錄賬號(hào)、密碼等安全信息,建議您及時(shí)修改。
實(shí)例的并行度設(shè)置不合理
排查步驟
多線程并行處理任務(wù)時(shí),由于每個(gè)線程處理的數(shù)據(jù)量不一致,可能會(huì)出現(xiàn)CXPACKET等待情況。CXPACKET等待發(fā)生較多時(shí),會(huì)造成CPU使用率高。您可以通過(guò)SSMS的活動(dòng)監(jiān)視器、或如下SQL代碼(多次執(zhí)行取差值),來(lái)監(jiān)控是否存在大量CXPACKET等待。
CXPACKET等待狀態(tài)出現(xiàn)在SQL Server的并行處理場(chǎng)景中,指某些線程已完成其分擔(dān)負(fù)載,而在等待其他并行線程完成,以便所有線程的結(jié)果匯合。CXPACKET等待時(shí)間如果積累過(guò)多,可能影響系統(tǒng)的CPU效能。
WITH [Waits] AS (
SELECT [wait_type],
[wait_time_ms] / 1000.0 AS [WaitS],
([wait_time_ms] - [signal_wait_time_ms]) / 1000.0 AS [ResourceS],
[signal_wait_time_ms] / 1000.0 AS [SignalS],
[waiting_tasks_count] AS [WaitCount],
100.0 * [wait_time_ms] / SUM ([wait_time_ms]) OVER() AS [Percentage],
ROW_NUMBER() OVER(
ORDER BY [wait_time_ms] DESC) AS [RowNum]
FROM sys.dm_os_wait_stats
WHERE [wait_type] NOT IN ( N'BROKER_EVENTHANDLER',
N'BROKER_RECEIVE_WAITFOR',
N'BROKER_TASK_STOP',
N'BROKER_TO_FLUSH',
N'BROKER_TRANSMITTER',
N'CHECKPOINT_QUEUE',
N'CHKPT',
N'CLR_AUTO_EVENT',
N'CLR_MANUAL_EVENT',
N'CLR_SEMAPHORE', -- Maybe uncomment these four if you have mirroring issues N'DBMIRROR_DBM_EVENT', N'DBMIRROR_EVENTS_QUEUE', N'DBMIRROR_WORKER_QUEUE', N'DBMIRRORING_CMD', N'DIRTY_PAGE_POLL', N'DISPATCHER_QUEUE_SEMAPHORE', N'EXECSYNC', N'FSAGENT', N'FT_IFTS_SCHEDULER_IDLE_WAIT', N'FT_IFTSHC_MUTEX', -- Maybe uncomment these six if you have AG issues N'HADR_CLUSAPI_CALL', N'HADR_FILESTREAM_IOMGR_IOCOMPLETION', N'HADR_LOGCAPTURE_WAIT', N'HADR_NOTIFICATION_DEQUEUE', N'HADR_TIMER_TASK', N'HADR_WORK_QUEUE', N'KSOURCE_WAKEUP', N'LAZYWRITER_SLEEP', N'LOGMGR_QUEUE', N'MEMORY_ALLOCATION_EXT', N'ONDEMAND_TASK_QUEUE', N'PREEMPTIVE_XE_GETTARGETSTATE', N'PWAIT_ALL_COMPONENTS_INITIALIZED', N'PWAIT_DIRECTLOGCONSUMER_GETNEXT', N'QDS_PERSIST_TASK_MAIN_LOOP_SLEEP', N'QDS_ASYNC_QUEUE', N'QDS_CLEANUP_STALE_QUERIES_TASK_MAIN_LOOP_SLEEP', N'QDS_SHUTDOWN_QUEUE', N'REDO_THREAD_PENDING_WORK', N'REQUEST_FOR_DEADLOCK_SEARCH', N'RESOURCE_QUEUE', N'SERVER_IDLE_CHECK', N'SLEEP_BPOOL_FLUSH', N'SLEEP_DBSTARTUP', N'SLEEP_DCOMSTARTUP', N'SLEEP_MASTERDBREADY', N'SLEEP_MASTERMDREADY', N'SLEEP_MASTERUPGRADED', N'SLEEP_MSDBSTARTUP', N'SLEEP_SYSTEMTASK', N'SLEEP_TASK', N'SLEEP_TEMPDBSTARTUP', N'SNI_HTTP_ACCEPT', N'SP_SERVER_DIAGNOSTICS_SLEEP', N'SQLTRACE_BUFFER_FLUSH', N'SQLTRACE_INCREMENTAL_FLUSH_SLEEP', N'SQLTRACE_WAIT_ENTRIES', N'WAIT_FOR_RESULTS', N'WAITFOR', N'WAITFOR_TASKSHUTDOWN', N'WAIT_XTP_RECOVERY', N'WAIT_XTP_HOST_WAIT', N'WAIT_XTP_OFFLINE_CKPT_NEW_LOG', N'WAIT_XTP_CKPT_CLOSE', N'XE_DISPATCHER_JOIN', N'XE_DISPATCHER_WAIT', N'XE_TIMER_EVENT') AND [waiting_tasks_count] > 0 )
SELECT MAX ([W1].[wait_type]) AS [WaitType],
CAST (MAX ([W1].[WaitS]) AS DECIMAL (16, 2)) AS [Wait_S],
CAST (MAX ([W1].[ResourceS]) AS DECIMAL (16, 2)) AS [Resource_S],
CAST (MAX ([W1].[SignalS]) AS DECIMAL (16, 2)) AS [Signal_S],
MAX ([W1].[WaitCount]) AS [WaitCount],
CAST (MAX ([W1].[Percentage]) AS DECIMAL (5, 2)) AS [Percentage],
CAST ((MAX ([W1].[WaitS]) / MAX ([W1].[WaitCount])) AS DECIMAL (16, 4)) AS [AvgWait_S],
CAST ((MAX ([W1].[ResourceS]) / MAX ([W1].[WaitCount])) AS DECIMAL (16, 4)) AS [AvgRes_S],
CAST ((MAX ([W1].[SignalS]) / MAX ([W1].[WaitCount])) AS DECIMAL (16, 4)) AS [AvgSig_S]
FROM [Waits] AS [W1]
INNER JOIN [Waits] AS [W2] ON [W2].[RowNum] <= [W1].[RowNum]
GROUP BY [W1].[RowNum]
HAVING SUM ([W2].[Percentage]) - MAX([W1].[Percentage]) < 95;
處理方法
語(yǔ)句級(jí)別進(jìn)行設(shè)置
執(zhí)行以下SQL語(yǔ)句,通過(guò)查詢語(yǔ)句尋找消耗CPU的語(yǔ)句。
SELECT TOP 50 [Avg. MultiCore/CPU time(sec)] = qs.total_worker_time / 1000000 / qs.execution_count, [Total MultiCore/CPU time(sec)] = qs.total_worker_time / 1000000, [Avg. Elapsed Time(sec)] = qs.total_elapsed_time / 1000000 / qs.execution_count, [Total Elapsed Time(sec)] = qs.total_elapsed_time / 1000000, qs.execution_count, [Avg. I/O] = (total_logical_reads + total_logical_writes) / qs.execution_count, [Total I/O] = total_logical_reads + total_logical_writes, Query = SUBSTRING(qt.[text], (qs.statement_start_offset / 2) + 1, ((CASE qs.statement_end_offset WHEN -1 THEN DATALENGTH(qt.[text]) ELSE qs.statement_end_offset END - qs.statement_start_offset) / 2) + 1), Batch = qt.[text], [DB] = DB_NAME(qt.[dbid]), qs.last_execution_time, qp.query_plan FROM sys.dm_exec_query_stats AS qs CROSS APPLY sys.dm_exec_sql_text(qs.[sql_handle]) AS qt CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) AS qp where qs.execution_count > 5 --more than 5 occurences ORDER BY [Total MultiCore/CPU time(sec)] DESC;
說(shuō)明對(duì)于RDS SQL Server 2008 R2實(shí)例,可以在RDS控制臺(tái)查看慢日志統(tǒng)計(jì),查找消耗CPU的語(yǔ)句。
查看方法:進(jìn)入RDS實(shí)例詳情頁(yè)面,在左側(cè)導(dǎo)航欄單擊日志管理,在慢日志統(tǒng)計(jì)頁(yè)簽下查看。
識(shí)別高并行度SQL語(yǔ)句后,查看其執(zhí)行計(jì)劃,對(duì)這類查詢,可在語(yǔ)句末添加并行度控制提示,如
OPTION (MAXDOP 1)
, 來(lái)約束并行執(zhí)行,優(yōu)化資源管理。示例如下:SELECT column1,column2 FROM table1 o INNER JOIN table2 d ON (o.d_id = d.d_id) OPTION (maxdop 1);
實(shí)例級(jí)別進(jìn)行設(shè)置
執(zhí)行以下SQL語(yǔ)句,查看當(dāng)前實(shí)例的MAXDOP(Maximum Degree of Parallelism)值。
SELECT * FROM SYS.CONFIGURATIONS WHERE NAME LIKE '%MAX%';
執(zhí)行以下SQL語(yǔ)句,在實(shí)例級(jí)別設(shè)置該參數(shù),對(duì)所有查詢均生效。
sp_rds_configure 'max degree of parallelism',1;
說(shuō)明對(duì)于RDS SQL Server 2008 R2實(shí)例,可以在RDS管理控制臺(tái)對(duì)參數(shù)進(jìn)行手動(dòng)設(shè)置。具體操作,請(qǐng)參見(jiàn)使用控制臺(tái)設(shè)置參數(shù)。
應(yīng)用負(fù)載高
現(xiàn)象描述
當(dāng)應(yīng)用負(fù)載較高時(shí),并未觀察到慢查詢問(wèn)題(或者慢查詢并非導(dǎo)致系統(tǒng)性能的主要原因),且QPS和CPU使用率曲線變化吻合。常見(jiàn)于應(yīng)用優(yōu)化過(guò)的在線事務(wù)交易系統(tǒng)(比如訂單系統(tǒng))、高讀取率的熱門(mén)Web網(wǎng)站應(yīng)用等。
特征概括
實(shí)例的QPS高,查詢比較簡(jiǎn)單、執(zhí)行效率高、優(yōu)化空間小。
處理方法
建議從應(yīng)用架構(gòu)、實(shí)例規(guī)格等方面來(lái)解決:
升級(jí)實(shí)例規(guī)格,增加CPU資源。更多詳情,請(qǐng)參見(jiàn)變更配置。
盡量?jī)?yōu)化查詢,減少查詢的執(zhí)行成本(邏輯IO,執(zhí)行需要訪問(wèn)的表數(shù)據(jù)行數(shù)),提高應(yīng)用可擴(kuò)展性。
查詢語(yǔ)句的讀寫(xiě)過(guò)高
現(xiàn)象描述
存在慢查詢,QPS和CPU使用率曲線變化不吻合,檢查消耗CPU的語(yǔ)句,存在I/O較大的語(yǔ)句。
特征概括
實(shí)例的QPS不高,查詢執(zhí)行效率低、執(zhí)行需要掃描大量表中數(shù)據(jù)、優(yōu)化空間大。
處理方法
對(duì)于大表查詢,檢查是否有合適的索引。檢查實(shí)際執(zhí)行計(jì)劃,針對(duì)全表掃描操作進(jìn)行優(yōu)化,執(zhí)行計(jì)劃中也會(huì)給出缺失索引的建議。
通過(guò)CloudDBA檢查性能問(wèn)題。更多詳情,請(qǐng)參見(jiàn)空間管理。
更多建議
避免出現(xiàn)CPU使用100%的一般原則如下:
設(shè)置CPU使用率告警,實(shí)例CPU使用率保證一定的冗余度。
應(yīng)用設(shè)計(jì)和開(kāi)發(fā)過(guò)程中,要考慮查詢的優(yōu)化,遵守SQL優(yōu)化的一般優(yōu)化原則,降低查詢的邏輯I/O,提高應(yīng)用可擴(kuò)展性。
新功能、新模塊上線前,要使用生產(chǎn)環(huán)境數(shù)據(jù)進(jìn)行壓力測(cè)試。
經(jīng)常使用CloudDBA查看實(shí)例各項(xiàng)性能,及時(shí)發(fā)現(xiàn)問(wèn)題。