mysql卡頓問題查找和解決方法
版權
一、所遇問題
寫在前邊的廢話:今天面試阿里的時候問到過類似問題,以前做調優的時候都是現查現用,缺乏總結,面試時答得也不好,今天趁此機會做一個梳理,知識只有沉淀下來才是自己的東西。
問題:mysql 運行過程中超級卡頓,並出現CPU使用率居高不下的情況,如何定位問題點以及如何解決?
二、占用CPU過高,可能原因
1)一般來講,排除高並發的因素,還是要找到導致你CPU過高的哪幾條在執行的SQL,show processlist語句,查找負荷最重的SQL語句,優化該SQL,比如適當建立某字段的索引;
2)打開慢查詢日志,將那些執行時間過長且占用資源過多的SQL拿來進行explain分析,導致CPU過高,多數是GroupBy、OrderBy排序問題所致,然后慢慢進行優化改進。比如優化insert語句、優化group by語句、優化order by語句、優化join語句等;
3)考慮定時優化文件及索引;
4)定期分析表,使用optimize table;
5)優化數據庫對象;
6)考慮是否是鎖問題;
7)調整一些MySQL Server參數,比如key_buffer_size、table_cache、innodb_buffer_pool_size、innodb_log_file_size等;
8)如果數據量過大,可以考慮使用MySQL集群或者搭建高可用環境。
9)可能由於內存latch(泄露)導致數據庫CPU高
10)在多用戶高並發的情況下,任何系統都會hold不住,所以使用緩存是必須的,使用memcached或者redis緩存都可以;
11)看看tmp_table_size大小是否偏小,如果允許,適當的增大一點;
12)如果max_heap_table_size配置的過小,增大一點;
13)mysql的sql語句睡眠連接超時時間設置問題(wait_timeout)
14)使用show processlist查看mysql連接數,看看是否超過了mysql設置的連接數
三、案例一(臨時表過大)
MySQL負載居高不下,如果打開了慢查詢日志功能,最好的辦法就是針對慢查詢日志里執行慢的sql語句進行優化,如果sql語句用了大量的group by等語句,union聯合查詢等肯定會將mysql的占用率提高。所以就需要優化sql語句除了優化sql語句外,也可以做一些配置上的優化。在mysql中運行show proceslist;出現下面回顯結果:
1.查詢有大量的Copying to tmp table on disk狀態明顯是由於臨時表過大導致mysql將臨時表寫入硬盤影響了整體性能。Mysql中tmp_table_size的默認值僅為16MB,在當前的情況下顯然是不夠用的。
mysql> show variables like "%tmp%";+-------------------+----------+| Variable_name | Value |+-------------------+----------+| max_tmp_tables | 32 || slave_load_tmpdir | /tmp || tmp_table_size | 16777216 || tmpdir | /tmp |+-------------------+----------+4 rows in set (0.00 sec)
解決辦法:調整臨時表大小
1)進mysql終端命令修改,加上global,下次進mysql就會生效mysql> set global tmp_table_size=33554432;Query OK, 0 rows affected (0.00 sec)
再次登陸mysqlmysql> show variables like "%tmp%";+-------------------+----------+| Variable_name | Value |+-------------------+----------+| max_tmp_tables | 32 || slave_load_tmpdir | /tmp || tmp_table_size | 33554432 || tmpdir | /tmp |+-------------------+----------+4 rows in set (0.01 sec)
2)my.cnf配置文件修改[root@www ~]# vim my.cnf.....tmp_table_size = 32M
重啟mysql[root@www ~]# /etc/init.d/mysqld restart
四、慢查詢日志
MySQL的慢查詢日志是MySQL提供的一種日志記錄,它用來記錄在MySQL中響應時間超過閥值的語句,具體指運行時間超過long_query_time值的SQL,則會被記錄到慢查詢日志中。long_query_time的默認值為10,意思是運行10S以上的語句。默認情況下,Mysql數據庫並不啟動慢查詢日志,需要我們手動來設置這個參數,當然,如果不是調優需要的話,一般不建議啟動該參數,因為開啟慢查詢日志會或多或少帶來一定的性能影響。慢查詢日志支持將日志記錄寫入文件,也支持將日志記錄寫入數據庫表。參考文章:https://blog.csdn.net/m_nanle_xiaobudiu/article/details/79288257