日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

CPU 占用過高常見現(xiàn)象

在使用 MySQL 的過程中會遇到各種瓶頸問題,常見的是 IO 瓶頸,但是有時候會出現(xiàn)服務(wù)器 CPU 使用率超過 100%,應(yīng)用頁面訪問慢,登錄服務(wù)器負(fù)載很高。而導(dǎo)致這個問題竟然是 MySQL 進(jìn)程,按理說如果 MySQL 運(yùn)行穩(wěn)定,服務(wù)器的 CPU 資源并不會跑滿,如果出現(xiàn)這個問題,初步可以斷定,是 MySQL 實例中出現(xiàn)了問題 SQL。

CPU 占用過高常見原因

CPU 占用過高常見原因:

  • 服務(wù)器硬件問題
  • 內(nèi)存溢出
  • 業(yè)務(wù)高并發(fā)

如果是業(yè)務(wù)高并發(fā)引起,可以理解為一種業(yè)務(wù)繁忙的狀態(tài),有可能業(yè)務(wù)猛增,有可能是定期或者臨時的并發(fā)窗口:

  • 數(shù)據(jù)庫對象設(shè)計不合理
  • 觸發(fā)器導(dǎo)致
  • 表索引設(shè)計不合理
  • 數(shù)據(jù)庫鎖導(dǎo)致,如行鎖沖突、行鎖等待、鎖超時、死鎖等
  • 系統(tǒng)架構(gòu)沒有緩存中間件
  • 讀寫分離配置不合理
  • OLTP 系統(tǒng)承載了 OLAP 的業(yè)務(wù)需求
  • 未合理升級改造為集群環(huán)境
  • 未配置異構(gòu)數(shù)據(jù)分析系統(tǒng)
  • MySQL 系統(tǒng)參數(shù)設(shè)置不合理
  • 問題 SQL 導(dǎo)致

SQL 問題導(dǎo)致 CPU 使用率過高是最常見的現(xiàn)象,比如 group by、order by、join 等,這些很大程度影響 SQL 執(zhí)行效率,從而占用大量的系統(tǒng)資源。

說了這么多常見原因,其實總結(jié)一句話來說就是現(xiàn)有系統(tǒng)的現(xiàn)有配置下的現(xiàn)有環(huán)境提供不了所需要的數(shù)據(jù)查詢、分析、執(zhí)行能力,針對這個問題,首先我們要發(fā)現(xiàn)問題的所在,就是說我們要準(zhǔn)確的定位問題,然后針對問題進(jìn)行優(yōu)化,再考慮其他升級改造的事情。

定位分析問題 SQL

光說不練假把式,接下來我們比劃比劃。

首先,搭建一套模擬環(huán)境,這里我讓我的得力助手 DBdeployer 來幫我搭建一套模擬環(huán)境。

DBdeployer 是用 Go 語言實現(xiàn)的一款非常強(qiáng)大與高效的部署數(shù)據(jù)庫環(huán)境的開源工具,我們完全可以用它來部署開發(fā)、測試環(huán)境。如果你對這個助手感興趣,可以看我的另外一篇 Chat。

MySQL 安裝部署:我是如何“秒級”部署 MySQL 集群

使用 DBdeployer 來部署一個單點 5.7.27 版本的 MySQL,并配置一個模擬 CPU 占比高的測試環(huán)境。

[root@localhost ~]# dbdeployer deploy single 5.7.27
Database installed in /dbdata/sandboxes/msb_5_7_27
run 'dbdeployer usage single' for basic instructions'
.. sandbox server started

創(chuàng)建測試表:

[root@localhost ~]# cd /dbdata/sandboxes/msb_5_7_27/
[root@localhost msb_5_7_27]# ./use 
mysql [localhost:5727] {msandbox} ((none)) > use test
Database changed
mysql [localhost:5727] {msandbox} (test) > create table t_cpu(id int primary key auto_increment);        
Query OK, 0 rows affected (0.39 sec)

插入大量模擬測試數(shù)據(jù):

mysql [localhost:5727] {msandbox} (test) > insert into t_cpu values(),(),(),(),();
Query OK, 5 rows affected (0.06 sec)
Records: 5  Duplicates: 0  Warnings: 0
mysql [localhost:5727] {msandbox} (test) > insert into t_cpu select id+(select count(*) from t_cpu) from t_cpu;
Query OK, 5 rows affected (0.05 sec)
Records: 5  Duplicates: 0  Warnings: 0

......
......

mysql [localhost:5727] {msandbox} (test) > insert into t_cpu select id+(select count(*) from t_cpu) from t_cpu;
Query OK, 5242880 rows affected (1 min 8.84 sec)
Records: 5242880  Duplicates: 0  Warnings: 0

mysql [localhost:5727] {msandbox} (test) > select count(*) from t_cpu;                                         
+----------+
| count(*) |
+----------+
| 10485760 |
+----------+
1 row in set (2.22 sec)

至此我們已經(jīng)造了 10485760 條數(shù)據(jù)。

有 1000W+ 的數(shù)據(jù)量了,我們模擬一個業(yè)務(wù)場景,讓 CPU 嗨(high)起來。

執(zhí)行一個慢查詢:

mysql [localhost:5727] {msandbox} (test) > select * from t_cpu order by rand() limit 1;

另外開一個會話,top 看看進(jìn)程:

top - 15:21:20 up 33 days, 23:10,  3 users,  load average: 0.38, 0.19, 0.21
Tasks: 202 total,   2 running, 200 sleeping,   0 stopped,   0 zombie
%Cpu(s): 23.3 us,  3.6 sy,  0.0 ni, 73.1 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  8173716 total,  2867684 free,  1059276 used,  4246756 buff/cache
KiB Swap:  2097148 total,  2097140 free,        8 used.  6761912 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                                                              
32232 root      20   0 1443252 356688  11748 S 107.0  4.4   2:03.82 mysqld                                                                               
  296 root      20   0   67044  15588   1440 S   0.7  0.2 325:32.46 plymouthd                                                                            
  600 root      20   0  162032   2360   1580 R   0.3  0.0   0:04.21 top                                                                                  
 1901 gnome-i+  20   0  714116  22436   9168 S   0.3  0.3  98:46.20 gsd-color                                                                            
    1 root      20   0  191264   4192   2632 S   0.0  0.1  18:39.97 systemd                                                                              
    2 root      20   0       0      0      0 S   0.0  0.0   0:01.28 kthreadd                                                                             
    4 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kworker/0:0H                                                                         
    6 root      20   0       0      0      0 S   0.0  0.0   0:00.95 ksoftirqd/0                                                                          
    7 root      rt   0       0      0      0 S   0.0  0.0   0:02.08 migration/0                                                                          
    8 root      20   0       0      0      0 S   0.0  0.0   0:00.00 rcu_bh               

通過 top 我們發(fā)現(xiàn)有一個 32232 的進(jìn)程使得 CPU 使用率已經(jīng)超過了 100%。

接下來我們具體分析分析,究竟是什么導(dǎo)致 CPU 使用率達(dá)到 100%以上的。

檢查內(nèi)存使用情況

[root@localhost ~]# free -m
              total        used        free      shared  buff/cache   available
Mem:           7982        1033        2801          40        4147        6604
Swap:          2047           0        2047

內(nèi)存使用率還可以,應(yīng)該不是內(nèi)存影響導(dǎo)致的問題。

檢查服務(wù)器線程

方法一:

top -H -p <mysqld 進(jìn)程 id>

先通過 top 找出占用 CPU 使用率 100% 的 MySQL 進(jìn)程 32232,在具體查看該進(jìn)程下的線程情況。

[root@localhost ~]# top -H -p 32232
top - 15:30:32 up 33 days, 23:20,  3 users,  load average: 0.18, 0.15, 0.18
Threads:  28 total,   1 running,  27 sleeping,   0 stopped,   0 zombie
%Cpu(s): 24.4 us,  3.2 sy,  0.0 ni, 72.4 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  8173716 total,  2867420 free,  1059520 used,  4246776 buff/cache
KiB Swap:  2097148 total,  2097140 free,        8 used.  6761668 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND                                                                               
32272 root      20   0 1443252 356688  11748 R 99.7  4.4   2:25.74 mysqld                                                                                
32244 root       0 -20 1443252 356688  11748 S  3.7  4.4   0:08.68 mysqld                                                                                
32236 root      20   0 1443252 356688  11748 S  1.7  4.4   0:01.45 mysqld                                                                                
32237 root      20   0 1443252 356688  11748 S  1.7  4.4   0:01.43 mysqld                                                                                
32238 root      20   0 1443252 356688  11748 S  1.3  4.4   0:01.43 mysqld                                                                                
32239 root      20   0 1443252 356688  11748 S  1.3  4.4   0:01.42 mysqld                                                                                
32241 root      20   0 1443252 356688  11748 S  0.3  4.4   0:00.75 mysqld                                                                                
32250 root      20   0 1443252 356688  11748 S  0.3  4.4   0:00.98 mysqld                                                                                
32232 root      20   0 1443252 356688  11748 S  0.0  4.4   0:00.31 mysqld                                                                                
32233 root      20   0 1443252 356688  11748 S  0.0  4.4   0:00.00 mysqld                                                                                
32234 root      20   0 1443252 356688  11748 S  0.0  4.4   0:00.23 mysqld                                                                                
32235 root      20   0 1443252 356688  11748 S  0.0  4.4   0:00.31 mysqld                                                                                
32240 root      20   0 1443252 356688  11748 S  0.0  4.4   0:00.74 mysqld                                                                                
32242 root      20   0 1443252 356688  11748 S  0.0  4.4   0:00.72 mysqld                                                                                
32243 root      20   0 1443252 356688  11748 S  0.0  4.4   0:00.69 mysqld                                                                                
32247 root      20   0 1443252 356688  11748 S  0.0  4.4   0:00.16 mysqld                                                                                
32248 root      20   0 1443252 356688  11748 S  0.0  4.4   0:00.23 mysqld                                                                                
32249 root      20   0 1443252 356688  11748 S  0.0  4.4   0:00.02 mysqld                                                                                
32251 root      20   0 1443252 356688  11748 S  0.0  4.4   0:08.04 mysqld                                                                                
32252 root      20   0 1443252 356688  11748 S  0.0  4.4   0:00.00 mysqld                                                                                
32253 root      20   0 1443252 356688  11748 S  0.0  4.4   0:00.00 mysqld                                                                                
32254 root      20   0 1443252 356688  11748 S  0.0  4.4   0:00.00 mysqld                                                                                
32255 root      20   0 1443252 356688  11748 S  0.0  4.4   0:00.00 mysqld                                                                                
32256 root      20   0 1443252 356688  11748 S  0.0  4.4   0:00.18 mysqld                                                                                
32257 root      20   0 1443252 356688  11748 S  0.0  4.4   0:00.03 mysqld                                                                                
32258 root      20   0 1443252 356688  11748 S  0.0  4.4   0:00.00 mysqld                                                                                
32259 root      20   0 1443252 356688  11748 S  0.0  4.4   0:00.00 mysqld                                                                                
32260 root      20   0 1443252 356688  11748 S  0.0  4.4   0:00.00 mysqld      

結(jié)果可以明顯的看到 32272 這個線程的 CPU 使用率異常。

方法二:

pidstat -t -p <mysqld 進(jìn)程 id> 1 5

先通過 top 找出占用 CPU 使用率 100% 的 MySQL 進(jìn)程 32232,使用 pidstat 工具在具體查看該進(jìn)程下的線程情況。

pidstat -t -p 32232 1 5

Average:      UID      TGID       TID    %usr %system  %guest    %CPU   CPU  Command
Average:        0     32232         -   85.00   12.60    0.00   97.60     -  mysqld
Average:        0         -     32232    0.00    0.00    0.00    0.00     -  |__mysqld
Average:        0         -     32233    0.00    0.00    0.00    0.00     -  |__mysqld
Average:        0         -     32234    0.00    0.00    0.00    0.00     -  |__mysqld
Average:        0         -     32235    0.00    0.00    0.00    0.00     -  |__mysqld
Average:        0         -     32236    1.00    0.40    0.00    1.40     -  |__mysqld
Average:        0         -     32237    0.80    0.40    0.00    1.20     -  |__mysqld
Average:        0         -     32238    0.80    0.40    0.00    1.20     -  |__mysqld
Average:        0         -     32239    1.00    0.20    0.00    1.20     -  |__mysqld
Average:        0         -     32240    0.20    0.00    0.00    0.20     -  |__mysqld
Average:        0         -     32241    0.00    0.20    0.00    0.20     -  |__mysqld
Average:        0         -     32242    0.00    0.00    0.00    0.00     -  |__mysqld
Average:        0         -     32243    0.00    0.00    0.00    0.00     -  |__mysqld
Average:        0         -     32244    1.20    1.80    0.00    3.00     -  |__mysqld
Average:        0         -     32247    0.00    0.00    0.00    0.00     -  |__mysqld
Average:        0         -     32248    0.00    0.00    0.00    0.00     -  |__mysqld
Average:        0         -     32249    0.00    0.00    0.00    0.00     -  |__mysqld
Average:        0         -     32250    0.00    0.00    0.00    0.00     -  |__mysqld
Average:        0         -     32251    0.00    0.00    0.00    0.00     -  |__mysqld
Average:        0         -     32252    0.00    0.00    0.00    0.00     -  |__mysqld
Average:        0         -     32253    0.00    0.00    0.00    0.00     -  |__mysqld
Average:        0         -     32254    0.00    0.00    0.00    0.00     -  |__mysqld
Average:        0         -     32255    0.00    0.00    0.00    0.00     -  |__mysqld
Average:        0         -     32256    0.00    0.00    0.00    0.00     -  |__mysqld
Average:        0         -     32257    0.00    0.00    0.00    0.00     -  |__mysqld
Average:        0         -     32258    0.00    0.00    0.00    0.00     -  |__mysqld
Average:        0         -     32259    0.00    0.00    0.00    0.00     -  |__mysqld
Average:        0         -     32260    0.00    0.00    0.00    0.00     -  |__mysqld
Average:        0         -     32272   80.00    9.80    0.00   89.80     -  |__mysqld

結(jié)果可以明顯的看到 32272 這個線程的 CPU 使用率異常。

查看 MySQL 進(jìn)程

在 MySQL 中看看當(dāng)前連接是否有什么異常。

方法一:

mysql [localhost:5727] {msandbox} ((none)) > show full processlist;
+----+----------+-----------+------+---------+------+---------------------+---------------------------------------------+
| Id | User     | Host      | db   | Command | Time | State               | Info                                        |
+----+----------+-----------+------+---------+------+---------------------+---------------------------------------------+
|  3 | msandbox | localhost | test | Query   |    7 | Creating sort index | select * from t_cpu order by rand() limit 1 |
|  4 | msandbox | localhost | NULL | Query   |    0 | starting            | show full processlist                       |
+----+----------+-----------+------+---------+------+---------------------+---------------------------------------------+
2 rows in set (0.00 sec)

方法二:

mysql [localhost:5727] {msandbox} ((none)) > select * from information_schema.processlist;
+----+----------+-----------+------+---------+------+--------------+----------------------------------------------+
| ID | USER     | HOST      | DB   | COMMAND | TIME | STATE        | INFO                                         |
+----+----------+-----------+------+---------+------+--------------+----------------------------------------------+
|  5 | msandbox | localhost | test | Query   |    2 | Sending data | select * from t_cpu order by rand() limit 1  |
|  6 | msandbox | localhost | NULL | Query   |    0 | executing    | select * from information_schema.processlist |
|  4 | msandbox | localhost | NULL | Sleep   | 1401 |              | NULL                                         |
|  3 | msandbox | localhost | test | Sleep   | 1405 |              | NULL                                         |
+----+----------+-----------+------+---------+------+--------------+----------------------------------------------+
4 rows in set (0.00 sec)

參數(shù)說明:

  • id:標(biāo)識位,MySQL 進(jìn)程 ID,使用 kill id,可以殺掉某一個進(jìn)程
  • user:當(dāng)前連接的用戶
  • host:當(dāng)前連接的主機(jī)
  • db:連接的數(shù)據(jù)庫
  • command:執(zhí)行的數(shù)據(jù)庫操作類型
  • sleep:休眠狀態(tài)
  • Query:查詢狀態(tài)
  • connect:連接狀態(tài)
  • time:已經(jīng)執(zhí)行的時間,單位秒
  • info:已經(jīng)執(zhí)行的 SQL
  • state:SQL 執(zhí)行的狀態(tài),結(jié)果是 SQL 語句整個執(zhí)行狀態(tài)中的一個,其中包含很多狀態(tài),我們整理如下表:

MySQL 5.7 官方參考MySQL 8.0 官方參考

狀態(tài)

含義

After create

當(dāng)線程使用函數(shù)創(chuàng)建表(包括內(nèi)部臨時表)最后階段會出現(xiàn)這個狀態(tài),即使由于某些錯誤未能創(chuàng)建成功,也會標(biāo)識該狀態(tài)

altering table

服務(wù)端正在執(zhí)行 ALTER TABLE

Analyzing

線程正在計算 MyISAM 引擎表鍵值分布(例如 ANALYZE TABLE)

checking permissions

線程正在檢查服務(wù)端是否有執(zhí)行語句所需要的的權(quán)限

Checking table

線程正在執(zhí)行表的檢查工作

cleaning up

線程已經(jīng)處理了一個命令,并準(zhǔn)備釋放內(nèi)存并重置某些狀態(tài)

Closing tables

線程正在將表中修改的數(shù)據(jù)刷新到磁盤,同時正在關(guān)閉已經(jīng)用完的表。是一個能很快完成的動作,如果持續(xù)完不成,需要確認(rèn)磁盤空間是否用滿或者磁盤使用的負(fù)載很高

converting HEAP to ondisk

線程正在將內(nèi)部臨時表從 MEMORY 表轉(zhuǎn)換為磁盤表

copy to tmp table

線程正在執(zhí)行一個 ALTER TABLE 語句。在創(chuàng)建一個新表,然后將老表記錄復(fù)制到新表之前將是此狀態(tài)

Copying to group table

如果語句具有不同的條件 ORDER BY 和 GROUP BY 標(biāo)準(zhǔn),則按組對行進(jìn)行排序并將其復(fù)制到臨時表

Copying to tmp table

服務(wù)端正在復(fù)制到內(nèi)存中的臨時表

Copying to tmp table on disk

服務(wù)端正在復(fù)制到磁盤上的臨時表,臨時結(jié)果集變的太大(參考 8.4.4 節(jié),MySQL 內(nèi)部臨時表的使用),線程正在將臨時表從內(nèi)存更改為基于磁盤的格式來節(jié)省內(nèi)存

Creating index

線程正在執(zhí)行 MyISAM 表的 ALTER TABLE ... ENABLE KEYS

Creating sort index

線程正在處理 SELECT 使用內(nèi)部臨時表

creating table

線程正在創(chuàng)建表,包括創(chuàng)建臨時表

Creating tmp table

線程正在內(nèi)存中或者磁盤上創(chuàng)建臨時表,如果臨時表在內(nèi)存中創(chuàng)建之后轉(zhuǎn)換到磁盤,狀態(tài)為 Copying to tmp table on disk

committing alter table to storage engine

服務(wù)端完成 ALTER TABLE 并提交結(jié)果

deleting from main table

服務(wù)端正在執(zhí)行多表刪除的第一部分,僅刪除第一個表,保存列和偏移量用于刪除其他表

deleting from reference tables

服務(wù)端正在執(zhí)行多表刪除的第二部分,在其他表中刪除匹配的行

discard_or_import_tablespace

線程正在執(zhí)行 ALTER TABLE ... DISCARD TABLESPACE or ALTER TABLE ... IMPORT TABLESPACE 語句

end

結(jié)束狀態(tài),結(jié)束之前需要清理 ALTER TABLE, CREATE VIEW, DELETE, INSERT, SELECT, or UPDATE

executing

線程正在執(zhí)行語句

Execution of init_command

線程正在執(zhí)行變量 init_command system 中的語句

freeing items

線程執(zhí)行了一條命令,在此期間完成了一些項目的資源釋放,涉及如查詢緩存,這個狀態(tài)之后通常為 cleaning up

FULLTEXT initialization

服務(wù)端正在準(zhǔn)備執(zhí)行 natural-language 的全文檢索

init

該狀態(tài)在 ALTER TABLE, DELETE, INSERT, SELECT, or UPDATE 初始化之前,服務(wù)端在該狀態(tài)下會刷新二進(jìn)制日志和 InnoDB 日志,清理查詢緩存

Killed

有發(fā)送了一個 KILL 線程的請求,下次終止前會檢查 kill 標(biāo)志位。MySQL 會在每次主循環(huán)中檢查 kill 標(biāo)志位,有時該線程并不能立馬殺掉會保留短暫時間,如果該線程被其他線程鎖定,那么 kill 會在鎖釋放后生效

logging slow query

線程正在往慢日志中寫入語句

login

連接線程的初始狀態(tài),直到客戶端成功完成驗證

manage keys

服務(wù)端開啟或者關(guān)閉表的索引

Opening tables

線程正在打開表,這應(yīng)該是一個很快的過程,除非有些事情組織了打開表。例如 ALTER TABLE or a LOCK TABLE 會在結(jié)束前阻止打開表操作。再就是有必要檢查 table_open_cache 參數(shù)的值設(shè)置是否足夠大。

optimizing

服務(wù)端正在對查詢進(jìn)行初始化優(yōu)化

preparing

查詢優(yōu)化狀態(tài)

Purging old relay logs

線程正在刪除不需要的中繼日志

query end

處理完查詢,在 freeing items 之前的狀態(tài)

Receiving from client

服務(wù)端正在讀取客戶端的包,該狀態(tài)在 5.7.8 叫 Reading from net

Removing duplicates

查詢正在使用 SELECT DISTINCT,這個過程 MySQL 在早期階段無法完成,因此需要一個額外的階段在把結(jié)果返回給客戶端前需要刪除重復(fù)行

removing tmp table

線程在執(zhí)行完 SELECT 后刪除中間臨時表,如果沒有使用臨時表,無該狀態(tài)

rename

重命名表

rename result table

線程正在執(zhí)行 ALTER TABLE 語句,創(chuàng)建一個新表,重命名新表替換老表

Reopen tables

線程給表加鎖,但是發(fā)現(xiàn)在獲取表后發(fā)現(xiàn)表結(jié)構(gòu)發(fā)生了變化。當(dāng)釋放鎖,關(guān)閉表之后嘗試重新打開表

Repair by sorting

使用排序創(chuàng)建索引修復(fù)代碼

preparing for alter table

服務(wù)端正準(zhǔn)備就地執(zhí)行 ALTER TABLE

Repair done

線程已完成對 MyISAM 表的多線程修復(fù)

Repair with keycache

創(chuàng)建索引緩存修復(fù)代碼,比 Repair by sorting 慢的多

Rolling back

線程在回滾事務(wù)

Saving state

對于 MyISAM 表的修復(fù)和分析操作,線程將新表保存到.MYI 文件頭,狀態(tài)包含行數(shù),AUTO_INCREMENT 計數(shù)器,鍵值分布之類的信息

Searching rows for update

線程正在執(zhí)行第一階段查詢未更新的數(shù)據(jù),如果更新了索引所在行就會執(zhí)行有該狀態(tài)

Sending data

線程正在讀取和處理 SELECT 的行記錄,發(fā)送給客戶端,由于在這個狀態(tài)下的操作會執(zhí)行大量的磁盤訪問(讀),因此它通常是查詢生命周期最長的狀態(tài)。

Sending to client

服務(wù)端正在給客戶端發(fā)送包,在 5.7.8 該狀態(tài)叫 Writing to net

setup

線程開始執(zhí)行 ALTER TABLE 操作

Sorting for group

線程正在做排序來滿足 GROUP BY

Sorting for order

線程正在做排序來滿足 ORDER BY

Sorting index

線程正在做索引頁優(yōu)化來使得 MyISAM 表優(yōu)化操作期間有更高效的訪問

Sorting result

對于一個 SELECT 語句,類似不使用臨時表的 Creating sort index

starting

語句執(zhí)行的第一個狀態(tài)

statistics

服務(wù)端正在計算統(tǒng)計信息對一個查詢創(chuàng)建執(zhí)行計劃,如果持續(xù)很長時間,服務(wù)端可能正在執(zhí)行其他的操作

System lock

線程調(diào)用了 mysqllocktables(),并且一直未更新狀態(tài),這個狀態(tài)非常常見,可能有很多原因造成。

update

線程正準(zhǔn)備執(zhí)行更新操作

Updating

線程正在檢索要更新的行并且更新行

updating main table

服務(wù)端正在執(zhí)行多表更新的第一部分,僅更新第一個表,保存列和偏移量用于更新其他表

updating reference tables

服務(wù)端正在執(zhí)行多表更新的第二部分,在其他表中更新匹配的行

User lock

線程正在使用 GET_LOCK()請求或等待一個意向鎖,對于 SHOW PROFILE 這個狀態(tài)意味著線程請求鎖(但是不等鎖)

User sleep

線程正在調(diào)用 SLEEP()

Waiting for commit lock

FLUSH TABLES WITH READ LOCK 正在等待一個提交鎖

Waiting for global read lock

FLUSH TABLES WITH READ LOCK 正在等待全局讀鎖或者設(shè)置系統(tǒng)全局變量 read_only

Waiting for tables

線程得到一個表結(jié)構(gòu)變化的通知,需要重新打開表獲取新的表結(jié)構(gòu),該線程需要等待其他線程關(guān)閉該表。這個通知發(fā)生在另外的線程執(zhí)行了 FLUSH TABLES,ALTER TABLE,RENAME TABLE,REPAIR TABLE,ANALYZE TABLE or OPTIMIZE TABLE

Waiting for table flush

線程正在執(zhí)行 FLUSH TABLES,正在等待其他線程關(guān)閉他們的表,或者是線程得到一個表結(jié)構(gòu)變化的通知,需要重新打開表獲取新的表結(jié)構(gòu),該線程需要等待其他線程關(guān)閉該表。這個通知發(fā)生在另外的線程執(zhí)行了 FLUSH TABLES,ALTER TABLE,RENAME TABLE,REPAIR TABLE,ANALYZE TABLE or OPTIMIZE TABLE

Waiting for lock_type lock

服務(wù)端正在等待 THR_LOCK 鎖,或者是元數(shù)據(jù)鎖定子系統(tǒng)的鎖,其中 lock_type 是鎖的類型,等待 THR_LOCK 鎖(Waiting for table level lock),等待元數(shù)據(jù)鎖(Waiting for event metadata lock、Waiting for global read lock、Waiting for schema metadata lock、Waiting for stored function metadata lock、Waiting for stored procedure metadata lock、Waiting for table metadata lock、Waiting for trigger metadata lock)

Waiting on cond

線程正在等待條件變?yōu)?true 的狀態(tài),沒有具體可用的狀態(tài)信息

Writing to net

服務(wù)端正在網(wǎng)絡(luò)中寫包,在 5.7.8 中該狀態(tài)叫 Sending to client

通過結(jié)果我們可以大致看看如下的情況:

  • 是否有大量的未執(zhí)行查詢語句
  • 是否有正在執(zhí)行的 DML 語句
  • 是否有執(zhí)行了很長時間的 DDL 語句
  • 是否有鎖等情況

我們模擬的這個環(huán)境,show 的結(jié)果只有兩條,結(jié)果非常明顯,但是真正的生產(chǎn)環(huán)境不止這兩條結(jié)果,通過這個查詢結(jié)果,可以大致分析一下,并不能準(zhǔn)確定位,準(zhǔn)確的定位問題,需要進(jìn)行后續(xù)的操作。

根據(jù)問題線程 id 定位 MySQL 中的 SQL:

mysql [localhost:5727] {msandbox} ((none)) > select a.user,a.host,a.db,b.thread_os_id,b.thread_id,a.id processlist_id,a.command,a.time,a.state,a.info from information_schema.processlist a,performance_schema.threads b where a.id = b.processlist_id and b.thread_os_id=32272;
+----------+-----------+------+--------------+-----------+----------------+---------+------+--------------+---------------------------------------------+
| user     | host      | db   | thread_os_id | thread_id | processlist_id | command | time | state        | info                                        |
+----------+-----------+------+--------------+-----------+----------------+---------+------+--------------+---------------------------------------------+
| msandbox | localhost | test |        32272 |        32 |              7 | Query   |    2 | Sending data | select * from t_cpu order by rand() limit 1 |
+----------+-----------+------+--------------+-----------+----------------+---------+------+--------------+---------------------------------------------+
1 row in set (0.00 sec)
  • thread_os_id=32272,代表的是操作系統(tǒng)級別的線程 id
  • thread_id=32,代表的是 MySQL 內(nèi)部級別的線程 id
  • processlist_id=7,代表的是會話發(fā)起者的進(jìn)程 id,可 kill 的 id

根據(jù)問題線程 id 查看其他監(jiān)控指標(biāo):

mysql [localhost:5727] {msandbox} (performance_schema) > select * from performance_schema.events_statements_current where thread_id in (select thread_id from performance_schema.threads where thread_os_id = 32272)G;
*************************** 1. row ***************************
              THREAD_ID: 32
               EVENT_ID: 11
           END_EVENT_ID: 11
             EVENT_NAME: statement/sql/select
                 SOURCE: 
            TIMER_START: 93213362472684000
              TIMER_END: 93221551162460000
             TIMER_WAIT: 8188689776000
              LOCK_TIME: 993000000
               SQL_TEXT: select * from t_cpu order by rand() limit 1
                 DIGEST: 83dacab9df764f11291d0001e420012e
            DIGEST_TEXT: SELECT * FROM `t_cpu` ORDER BY `rand` ( ) LIMIT ? 
         CURRENT_SCHEMA: test
            OBJECT_TYPE: NULL
          OBJECT_SCHEMA: NULL
            OBJECT_NAME: NULL
  OBJECT_INSTANCE_BEGIN: NULL
            MYSQL_ERRNO: 0
      RETURNED_SQLSTATE: NULL
           MESSAGE_TEXT: NULL
                 ERRORS: 0
               WARNINGS: 0
          ROWS_AFFECTED: 0
              ROWS_SENT: 1
          ROWS_EXAMINED: 20971521
CREATED_TMP_DISK_TABLES: 1
     CREATED_TMP_TABLES: 1
       SELECT_FULL_JOIN: 0
 SELECT_FULL_RANGE_JOIN: 0
           SELECT_RANGE: 0
     SELECT_RANGE_CHECK: 0
            SELECT_SCAN: 1
      SORT_MERGE_PASSES: 0
             SORT_RANGE: 0
              SORT_ROWS: 1
              SORT_SCAN: 1
          NO_INDEX_USED: 0
     NO_GOOD_INDEX_USED: 0
       NESTING_EVENT_ID: NULL
     NESTING_EVENT_TYPE: NULL
    NESTING_EVENT_LEVEL: 0
1 row in set (0.00 sec)

ERROR: 
No query specified

通過這個結(jié)果我們可以查看具體的 SQL,看到有使用臨時表、使用了排序等信息。

CREATED_TMP_DISK_TABLES: 1  
CREATED_TMP_TABLES: 1  
SORT_ROWS: 1  
SORT_SCAN: 1  

其他排查手段之慢查詢?nèi)罩?/h1>

查詢慢日志情況:

mysql [localhost:5727] {msandbox} ((none)) > show variables like 'slow_query_log%';
+---------------------+------------------------------------------------------+
| Variable_name       | Value                                                |
+---------------------+------------------------------------------------------+
| slow_query_log      | ON                                                   |
| slow_query_log_file | /dbdata/sandboxes/msb_5_7_27/data/localhost-slow.log |
+---------------------+------------------------------------------------------+
2 rows in set (0.01 sec)

在慢日志中查看慢 SQL:

cat /dbdata/sandboxes/msb_5_7_27/data/localhost-slow.log

# Time: 2021-08-17T09:11:06.768816Z
# User@Host: msandbox[msandbox] @ localhost []  Id:     5
# Query_time: 7.984593  Lock_time: 0.000184 Rows_sent: 1  Rows_examined: 20971521
SET timestamp=1629191466;
select * from t_cpu order by rand() limit 1;

可以很清楚的查到慢 SQL:

select * from t_cpu order by rand() limit 1

執(zhí)行了有 7.984593 秒,返回結(jié)果為 1 行。

其他排查手段之排查日志

開啟排查日志功能:

更改排查日志為 TABLE 方式,默認(rèn)為 FILE 方式
mysql [localhost:5727] {msandbox} ((none)) > set global log_output='TABLE';
Query OK, 0 rows affected (0.00 sec)

mysql [localhost:5727] {msandbox} ((none)) > set global general_log=ON;
Query OK, 0 rows affected (0.00 sec)

執(zhí)行慢查詢:

select * from t_cpu order by rand() limit 1

查詢排查日志內(nèi)容:

mysql [localhost:5727] {msandbox} ((none)) > SELECT * from mysql.general_log ORDER BY event_time DESC;
+----------------------------+-----------------------------------+-----------+-----------+--------------+----------------------------------------------------------+
| event_time                 | user_host                         | thread_id | server_id | command_type | argument                                                 |
+----------------------------+-----------------------------------+-----------+-----------+--------------+----------------------------------------------------------+
| 2021-08-17 17:19:19.863849 | msandbox[msandbox] @ localhost [] |         2 |         0 | Query        | SELECT * from mysql.general_log ORDER BY event_time DESC |
| 2021-08-17 17:18:45.017615 | msandbox[msandbox] @ localhost [] |         5 |         0 | Query        | select * from t_cpu order by rand() limit 1              |
+----------------------------+-----------------------------------+-----------+-----------+--------------+----------------------------------------------------------+
2 rows in set (0.00 sec)

結(jié)果顯示了剛才的慢 SQL,還有我們查詢排查日志結(jié)果的 SQL,其實慢日志會記錄所有的 SQL,我們只能通過這個日志內(nèi)容查看一些不太正常的 SQL,比如大量相同的 SQL;定期出現(xiàn)的 SQL;分析一個特定的事務(wù)等,排查日志模式非常影響 MySQL 性能,慎用。

關(guān)閉排查日志模式:

mysql [localhost:5727] {msandbox} ((none)) > set global general_log=OFF;
Query OK, 0 rows affected (0.05 sec)

mysql [localhost:5727] {msandbox} ((none)) > truncate table mysql.general_log;
Query OK, 0 rows affected (0.05 sec)

到目前為止,介紹了幾種常用的 MySQL 占用 CPU 過高的定位方法,你是否掌握了。找到問題了,接下來,我們就需要看看如何優(yōu)化這個問題了。

優(yōu)化一下也不難

前面介紹了幾種常用的排查 MySQL 占用 CPU 過高問題排查的方法,那么當(dāng)我們遇到問題了,如何解決,如何優(yōu)化呢?

首先,最暴力的方法,如果我們確定這個 SQL 可以被干掉,我們直接 kill id 即可。id 為 process 的 id。

其次,具體問題具體分析,如何排查問題是如何發(fā)生的,根據(jù)不同的問題作出相應(yīng)的解決方法。

1. 優(yōu)化 SQL,從邏輯上優(yōu)化 SQL,降低 SQL 復(fù)雜度,降低 MySQL 執(zhí)行成本。

2. 對 where、join、max()、min()、order by、group by 等子句用到的字段,創(chuàng)建相應(yīng)的索引。

3. 二級索引的正確使用。

4. 參數(shù)優(yōu)化:

  • 增加 tmp_table_size 大小
  • 增加 max_heap_table_size 大小
  • 調(diào)整 key_buffer_size、table_cache、innodb_buffer_pool_size、innodb_log_file_size 參數(shù)大小

其他常用優(yōu)化方法

1. 檢查 MySQL 連接數(shù)當(dāng)前使用是否超過限制

如果超出限制,而且之前的連接沒有得到釋放,那新的連接肯定會連接不到,造成連接延遲,影響效率。

2. MySQL 的 timeout 參數(shù)設(shè)置問題

這里介紹兩個參數(shù):

  • wait_timeout:MySQL 在關(guān)閉一個非交互的連接之前所要等待的秒數(shù),其取值范圍在 windows 系統(tǒng)中為 1-2147483,linux 系統(tǒng)中為 1-31536000,默認(rèn)值 28800。
  • interactive_time:MySQL 在關(guān)閉一個交互的連接之前所要等待的秒數(shù)(如 mysql gui tool 中的連接),其取值范圍隨 wait_timeout 變動,默認(rèn)值 28800。

交互連接即在 mysql_real_connect() 函數(shù)中使用了 CLIENT_INTERACTIVE 選項。簡單說,就是通過 MySQL 客戶端連接數(shù)據(jù)庫是交互式連接,通過 jdbc 連接數(shù)據(jù)庫是非交互式連接。在 MySQL 默認(rèn)設(shè)置下,當(dāng)一個連接的空閑時間超過 8 小時后,當(dāng)業(yè)務(wù)出現(xiàn)了高峰期,肯定會造成有太多的 TCP 連接沒關(guān)閉,數(shù)據(jù)庫連接數(shù)肯定會不夠用。從而會產(chǎn)生 CPU 占用過高,服務(wù)器告警等問題。因 EPG 的一個訪問一次對數(shù)據(jù)庫操作量不大,查詢完數(shù)據(jù)就完成 ok 了,wait_timeout 設(shè)置在 120s 內(nèi)就可以了。

在 MySQL 的官網(wǎng)了解到修改以上兩個參數(shù)必須修改 interactive_timeout。如果修改 interactive_timeout,則 wait_timeout 也發(fā)生變化,如果只修改 wait_timeout,不生效。

3. 老生常談,規(guī)范的 SQL 也是非常必要的

好了,至此我們基本學(xué)習(xí)完本節(jié)內(nèi)容了,內(nèi)容比較多,當(dāng)然也有不足之處,歡迎朋友們指正補(bǔ)充。

分享到:
標(biāo)簽:MySQL
用戶無頭像

網(wǎng)友整理

注冊時間:

網(wǎng)站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學(xué)四六

運(yùn)動步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績評定2018-06-03

通用課目體育訓(xùn)練成績評定