若是一臺服務器出現長時間負載太高 /週期性負載過大,或偶爾卡住如何來處理?mysql
是週期性的變化仍是偶爾問題?是服務器總體性能的問題, 仍是某單條語句的問題?sql
具體到單條語句, 這條語句是在等待上花的時間,仍是查詢上花的時間?緩存
觀察服務器狀態, 通常用以下2個命令bash
Show status;
Show processlist;
例: mysql> show status;服務器
#mysqladmin ext性能
解決辦法:優化
1: 減小無關請求(業務邏輯層面,暫不討論,但實際上是最有效的手段)spa
2: 若是請求數是必定的,不可減小的. 咱們要儘可能讓請求數平穩,不要有劇烈波動.code
不少時候,不是服務器撐不住總的查詢量,而是在某個時間段撐不住高峯請求.blog
不規則的延遲現象每每是因爲效率低下的語句形成的,如何抓到這些效率低的語句.
能夠用show processlist命令長期觀察,或用慢查詢.
Show processlist;
這個命令是顯示當前全部鏈接的工做狀態.
#!/bin/bash
while true
do
mysql -uroot -e 'show processlist\G'|grep State:|uniq -c|sort -rn
echo '---'
sleep 1
Done
若是觀察到如下狀態,則須要注意
converting HEAP to MyISAM 查詢結果太大時,把結果放在磁盤 (語句寫的很差,取數據太多)
create tmp table 建立臨時表(如group時儲存中間結果,說明索引建的很差)
Copying to tmp table on disk 把內存臨時表複製到磁盤 (索引很差,表字段選的很差)
locked 被其餘查詢鎖住 (通常在使用事務時易發生,互聯網應用不常發生)
logging slow query 記錄慢查詢
查看profile是否開啓
Show variables like ‘profiling’
開啓profile
set profiling=on;
查看profiles;
show profiles;
查看profile;
show profile for query 1;
2. 如何定位到有問題的語句?
在處理請求的某些場景中,服務器建立內部臨時表. 即表以MEMORY引擎在內存中處理,或以MyISAM引擎儲存在磁盤上處理.若是表過大,服務器可能會把內存中的臨時錶轉存在磁盤上.
用戶不能直接控制服務器內部用內存仍是磁盤存儲臨時表
若是group by 的列沒有索引,必產生內部臨時表,
若是order by 與group by爲不一樣列時,或多表聯查時order by ,group by 包含的列不是第一張表的列,將會產生臨時表
distinct 與order by 一塊兒使用可能會產生臨時表
若是使用SQL_SMALL_RESULT,MySQL會使用內存臨時表,除非查詢中有一些必需要把臨時表創建在磁盤上.
union合併查詢時會用到臨時表
某些視圖會用到臨時表,如使用temptable方式創建,或使用union或聚合查詢的視圖
想肯定查詢是否須要臨時表,能夠用EXPLAIN查詢計劃,並查看Extra列,看是否有Using temporary.
若是一開始在內存中產生的臨時表變大,會自動轉化爲磁盤臨時表. 內存中臨時表的最大值爲tmp_table_size和max_heap_size中較小值.
這和create table時顯示指定的內存表不同:這些表只受max_heap_table_size系統參數影響.
當服務器建立內部臨時表(不管在內存仍是在磁盤),create_tmp_tables變量都會增長.
若是建立了在磁盤上內部臨時表(不管是初始建立仍是由in-memory轉化),
create_tmp_disk_tables 變量都會增長.
一些狀況下限制了內存臨時表的使用,而使用磁盤臨時表:
(使用了內部臨時表的前提下) 語句中存在BLOB或TEXT列
在GROUP BY 或 DISTINCT子句中有大於512字節的string列
在UNION或UNION ALL時,SELECT語句裏有大於512字節的string列.
建表: 表結構的拆分,如核心字段都用int,char,enum等定長結構;非核心字段,或用到text,超長的varchar,拆出來單放一張表.
建索引: 合理的索引能夠減小內部臨時表(索引優化策略裏詳解)
寫語句: 不合理的語句將致使大量數據傳輸以及內部臨時表的使用.