在Linux系統中,經常會因為負載過高導致各種性能問題。那么如何進行排查,其實是有跡可循,而且模式固定。
本次就來分享一下,CPU占用過高、磁盤IO占用過高的排查方法。
還是那句話,以最佳實踐入手,真傳一句話,假傳萬卷書。這就是工作中學習和讀死書的區別與真相。
CPU占用率過高問題排查方法
-
使用mpstat查看cpu使用情況。
# mpstat 是一款 CPU 性能指標實時展示工具
# 能展示每個 CPU 核的資源視情況,同時還能將資源使用情況進行匯總展示
# 如果CPU0 的 %idle 已經為 0 ,說明此核已經非常繁忙
# 打印所有cpu核的情況(ALL),每隔1s打印一次,共打印5次
mpstat -P ALL 1 5
mpstat命令執行結果
從上面可以看到,服務器有 2 個 CPU(分別為0、1),每個 CPU 核的資源使用情況,也能很清晰的展示。
當服務器有特別多的 CPU 核,有時候看 CPU 匯總信息,發現 CPU 的 idle 很高,但是上面跑的應用程序卻很慢,這個時候就需要看看每個核的資源試用情況了。
重點關注指標:
* %iowait:代表在監控的時間間隔內,等待硬盤 I/O 的時間,如果此值比較高,說明 IO 非常繁忙
* %idle:代表在監控的時間間隔內,CPU 閑置時間所占用的時間百分比,此值越大,代表 CPU 越空閑
2. 使用pidstat查看消耗cpu資源的進程。
# 參數-u表明監控cpu使用情況
# 參數2表示每隔2s輸出一次,會循環輸出
pidstat -u 2
Linux 3.10.0-957.el7.x86_64 (mysql) 12/30/2020 _x86_64_ (1 CPU)
04:57:41 PM UID PID %usr %system %guest %CPU CPU Command
04:57:43 PM 2001 10733 0.00 91.44 0.00 91.44 0 mysqld
04:57:43 PM 2001 12635 0.00 0.53 0.00 0.53 0 pidstat
從上面的結果可以看到,導致 CPU0 資源被耗盡的元兇是 mysqld 進程,占用91.44%,需要定位具體線程。
pidstat 是一個非常強大的性能指標監控工具,建議掌握,此工具可以用來監控全部或指定進程的 CPU、mem、線程,IO 的資源的使用情況。
# 參數-d表示監控進程對磁盤的使用情況pidstat -d 2
Linux 3.10.0-957.el7.x86_64 (mysql) 12/30/2020 _x86_64_ (1 CPU)
03:57:47 PM UID PID kB_rd/s kB_wr/s kB_ccwr/s Command
03:57:49 PM 2001 10733 139.13 0.00 0.00 mysqld
03:57:49 PM UID PID kB_rd/s kB_wr/s kB_ccwr/s Command
03:57:51 PM 2001 10733 34034.78 0.00 0.00 mysqld
可以查看指定進程的線程 CPU 資源使用情況。
# 參數 -t,可以獲取指定進程的線程的 CPU 使用情況
pidstat -t 2 -p 10733
3. 使用 pidstat 查看消耗 CPU 資源的線程
pidstat -t 2 -p 10733
Linux 3.10.0-957.el7.x86_64 (mysql) 12/30/2020 _x86_64_ (1 CPU)
05:00:53 PM UID TGID TID %usr %system %guest %CPU CPU Command
05:00:55 PM 2001 10733 - 0.00 91.30 0.00 91.30 0 mysqld
05:00:55 PM 2001 - 10733 0.00 0.00 0.00 0.00 0 |__mysqld
05:00:55 PM 2001 - 10734 0.00 0.00 0.00 0.00 0 |__mysqld
05:00:55 PM 2001 - 10735 0.00 0.00 0.00 0.00 0 |__mysqld
05:00:55 PM 2001 - 10736 0.00 0.00 0.00 0.00 0 |__mysqld
05:00:55 PM 2001 - 10737 0.00 0.00 0.00 0.00 0 |__mysqld
05:00:55 PM 2001 - 10738 0.00 0.00 0.00 0.00 0 |__mysqld
05:00:55 PM 2001 - 10739 0.00 0.00 0.00 0.00 0 |__mysqld
05:00:55 PM 2001 - 10740 0.00 0.00 0.00 0.00 0 |__mysqld
05:00:55 PM 2001 - 10741 0.00 0.00 0.00 0.00 0 |__mysqld
05:00:55 PM 2001 - 10742 0.00 0.00 0.00 0.00 0 |__mysqld
05:00:55 PM 2001 - 10743 0.00 0.00 0.00 0.00 0 |__mysqld
05:00:55 PM 2001 - 10744 0.00 0.00 0.00 0.00 0 |__mysqld
05:00:55 PM 2001 - 10745 0.00 0.00 0.00 0.00 0 |__mysqld
05:00:55 PM 2001 - 10747 0.00 0.00 0.00 0.00 0 |__mysqld
05:00:55 PM 2001 - 10748 0.00 0.00 0.00 0.00 0 |__mysqld
05:00:55 PM 2001 - 10749 0.00 0.00 0.00 0.00 0 |__mysqld
05:00:55 PM 2001 - 10750 0.00 0.00 0.00 0.00 0 |__mysqld
05:00:55 PM 2001 - 10751 0.00 0.00 0.00 0.00 0 |__mysqld
05:00:55 PM 2001 - 10752 0.00 0.00 0.00 0.00 0 |__mysqld
05:00:55 PM 2001 - 10753 0.00 0.00 0.00 0.00 0 |__mysqld
05:00:55 PM 2001 - 10754 0.00 0.00 0.00 0.00 0 |__mysqld
05:00:55 PM 2001 - 10755 0.00 0.00 0.00 0.00 0 |__mysqld
05:00:55 PM 2001 - 10756 0.00 0.00 0.00 0.00 0 |__mysqld
05:00:55 PM 2001 - 10757 0.00 0.00 0.00 0.00 0 |__mysqld
05:00:55 PM 2001 - 10758 0.00 0.00 0.00 0.00 0 |__mysqld
05:00:55 PM 2001 - 10762 0.00 0.00 0.00 0.00 0 |__mysqld
05:00:55 PM 2001 - 10763 0.00 0.00 0.00 0.00 0 |__mysqld
05:00:55 PM 2001 - 10764 0.00 0.00 0.00 0.00 0 |__mysqld
05:00:55 PM 2001 - 10766 0.00 0.00 0.00 0.00 0 |__mysqld
05:00:55 PM 2001 - 10796 0.00 0.00 0.00 0.00 0 |__mysqld
05:00:55 PM 2001 - 10850 15.22 75.54 0.00 90.76 0 |__mysqld
可以很清楚看到是 10850 線程消耗了 CPU 資源,剩下的就根據操作系統的里線程 ID,去 MySQL 數據庫里排查,此線程正在執行的操作。
4. MySQL中查詢線程對應的具體SQL
-- 在 MySQL 5.7 版本,官方增加了一個視圖,專門記錄操作系統線程和數據庫進程之間關聯視圖。
-- 前面定位的最消耗 IO 和 CPU 的線程 ID 為 10850:
select PROCESSLIST_ID,
THREAD_OS_ID,
PROCESSLIST_USER,
PROCESSLIST_HOST,
PROCESSLIST_DB,
PROCESSLIST_COMMAND,
PROCESSLIST_INFO
from performance_schema.threads
where THREAD_OS_ID=10850;
磁盤IO占用率過高排查方法
-
使用 iostat 查看磁盤 IO 的讀寫情況。
#?每隔1s輸出一次
iostat?-mxt?1
# 每隔1s輸出一次,共輸出2次
iostat -mxt 1 2
iostat命令輸出
如果看到 %util 比較高,說明磁盤設備繁忙,需要定位到底是那個操作系統進程導致的大量讀操作。
iostat 是一款用于監控系統設備的 IO 負載情況的工具,在運維工作中會被高頻使用的工具之一。
# 常用參數介紹
* -m:輸出結果以兆為單位顯示
* -t:輸出結果中顯示時間戳
* -x:顯示和 IO 相關的擴展數據,包括每個設備的讀寫、合并讀、合并寫、讀寫等待情況
# 輸出指標介紹
* rrqm/s:每秒合并讀的條目
* wrqm/s:每秒合并寫的條目
* r/s:每秒 read I/O 設備次數
* w/s:每秒 write I/O 設備次數
* rMB/s: 每秒讀取 M 字節數
* wMB/s:每秒寫 M 字節數
* avgrq-sz:每次設備 I/O 操作平均數據大小
* avgqu-sz:I/O 隊列平均長度
* await:每次設備 I/O 操作的平均等待時間,單位毫秒
* r_await:每次讀 I/O 操作的平均等待時間,單位毫秒
* w_await:每次寫 I/O 操作的平均等待時間,單位毫秒
* svctm:每次設備 I/O 操作的平均服務時間,單位毫秒
* %util:每秒中有百分之多少的時間用于 I/O 操作,此值越高,代表著磁盤越繁忙
2. 使用 iotop 定位最消耗 IO 資源的元兇
iotop -p 10733
可以看到10850 線程大量讀操作,導致 IO 資源被消耗殆盡。
iotop 是一款用于監視磁盤設備 I/O 使用狀況的工具,可監測到具體的線程使用的磁盤 IO 的信息,功能也是非常強大,可惜需要 root 權限,普通用戶沒有執行權限,所以一般會用 pidstat 工具來替代。
參數介紹:
-P:只顯示進程 IO 讀寫情況
-p:監控指定進程的 IO 讀寫情況
-u:指定用戶進程的 IO 讀寫情況
1. 查看指定用戶的的進程
iotop -u mysql -P
2. 查看指定用戶的進程和線程 IO 讀寫情況
iotop -u mysql
3. 查看指定進程的線程 IO 讀寫情況
iotop -p 10733
3. 根據線程定位具體SQL。
select PROCESSLIST_ID,
THREAD_OS_ID,
PROCESSLIST_USER,
PROCESSLIST_HOST,
PROCESSLIST_DB,
PROCESSLIST_COMMAND,
PROCESSLIST_INFO
from performance_schema.threads
where THREAD_OS_ID=10850;