mysql資料庫的效能問題排查是十分複雜的,具體方法視場景而定,這裡只做大致思路分析。
1. 整體考慮導致查詢效能低下的各種因素
導致sql查詢變慢的原因是多元化的,在遇到問題時首先要有乙個全方位的思考:
網路問題導致
應用層導致
**中是否有不合理的查詢
快取失效導致查詢風暴耗盡磁碟資源
mysql伺服器效能導致
是否是由伺服器上其它任務占用資源過多導致資源不足
磁碟io的讀寫速率是否太慢
mysql寫操作頻繁
mysql寫入大量資料到磁碟
mysql寫入大量日誌到磁碟
mysql寫入大量排序檔案到磁碟
mysql寫入大量臨時表到磁碟
併發度超過某個閥值時,innodb的擴充套件性限制導致查詢計畫的優化需要很長時間
innodb瘋狂重新整理髒頁導致內部嚴重阻塞
庫表結構設計不合理
sql語句設計有問題或效率低
索引實際沒有正常使用
2. 剖析mysql查詢
1. 剖析伺服器負載
捕獲查詢到查詢日誌檔案中
使用慢查詢日誌
5.0版本以前慢查詢日誌是秒級別,5.1版本以後以達到微秒級。
可以通過設定long_query_time=0來捕獲所有查詢。
如果長期開啟慢查詢日誌,要部署日誌輪轉(log rotation)工具。
當因許可權不足等原因無法在伺服器上記錄查詢時可使用pt-query-digest工具
通過--processlist選項不斷檢視show full processlist的輸出,記錄查詢第一次出現的時間和消失的時間。(精度差)
通過抓取tcp網路包,然後根據mysql客戶端/服務端通訊協議進行解析。(精度高)
通過tcpdump將網路包資料儲存到磁碟。
使用pt-query-digest的--type=tcpdump選項解析並分析查詢。
分析查詢日誌
使用pt-query-digist工具生成剖析報告(請勿直接開啟整個慢查詢日誌進行分析,避免浪費時間)
報告中v/m列提供了方差均之比的詳細資料,數值高的查詢對應的執行時間的變化較大,這類查詢通常都值得去優化。
pt-query-digest指定--explain選項,輸出中會增加一列簡要描述查詢的執行計畫。通過觀察v/m和執行計畫列,可以更容易識別出效能低下需要優化的查詢。
可以通過--limit和--outliers選項指定工具顯示更多查詢的詳細資訊。
可以通過查詢的id或排名匹配剖析統計和查詢的詳細報告。
2. 剖析單條查詢
使用show profiles;
5.1版本引入,預設禁用,可以會話級別開啟:set profiling = 1;
使用show profile for query #query_id;通過query_id列印一條查詢語句的詳細查詢報告,其中可以看到查詢執行的每個步驟及其花費的時間。(按執行順序排序,無法order by)。
直接查詢information_schema中對應的表,可以按需要的格式化輸出:
set @query_id = #query_id;
select state, sum(duration) as total_r,
round(
100 * sum(duration) /
select sum(duration)
from information_schema.profiling
where query_id = @query_id
), 2) as pct_r,
count(*) as calls,
sum(duration) / count(*) as "r/call",
from information_schema.profiling
where query_id = @query_id
group by state
order by total_r desc;
通過分析結果得到查詢時間太長可能存在的原因:
花大量時間將資料複製到臨時表。
考慮如何改寫查詢以避免使用臨時表。
提公升臨時表的使用效率。
傳送資料(sending data)花費時間太多。
使用show status;
此命令返回一些伺服器級別和會話級別的計數器。
show global status返回伺服器級別的從伺服器啟動開始計算的查詢次數統計。
很多有用的計數器:create_tmp_disk_tables磁碟臨時表、create_tmp_tables臨時表、handler_read_rnd_next沒有用到索引的讀操作等。
explain是通過估計得到的結果,無法確認臨時表是否是磁碟表。(磁碟表和記憶體表效能差異很大)
使用慢查詢日誌
執行show variables like 'slow_query_log';檢視慢查詢日誌是否開啟。
若沒有開啟找到my.cnf,新增如下內容sudo vim /usr/local/mysql/my.cnf
log_output=file
slow_query_log=on
slow_query_log_file = /tmp/mysql-slow.log
log_queries_not_using_indexes=on
long_query_time = 1
重啟mysql並執行以下操作檢視:
show variables like 'slow_query_log';
show variables like '%quer%';
先使用pt_query_digest生成的報告進行分析,然後有目標地使用慢查詢日誌。
通過位元組量偏移值byte 123直接跳轉到日誌對應部分:
tail -c +123 /tmp/mysql-slow.log | head -n100
使用performance schema
5.5版本新增的表但還不支援查詢級別的剖析資訊。
主要為了測量當為提公升伺服器效能而修改mysql源**時使用。
使用user_statistics表:
通過這些表可以對資料庫活動進行測量和審計
可以強制執行使用策略
對於共享主機環境這樣的多租戶環境也同樣有用
檢視這些表:
show tables from information_schema like '%_statistics';
一些有用的查詢:
可以查詢使用最多或使用最少的表和索引,通過讀取次數或更新次數,或兩者一起排序。
可以查詢從未使用的索引。
可以檢視複製使用者的connected_time和busy_time,以確認是否會很難跟上主庫的進度。
3. 診斷間接性問題
盡量不要使用試錯的方式解決問題,而是應該在有問題發生的地方通過觀察資源的使用情況並盡可能測量資料。
1. 確定是單條查詢問題還是伺服器問題
若果伺服器上所有程式都突然變慢,又突然變好,每一條查詢也都變慢了,那麼慢查詢可能就不一定是原因。
老版本mysql對高配置伺服器(多cpu)支援不好,新版本相對好些。此時可通過公升級mysql版本來解決問題。
下面是解決間接性問題的方法和工具:
以較高頻率執行show global status
以較高頻率執行show processlist
使用查詢日誌
用gnuplot或r等繪圖工具將結果繪製成圖形幫助分析
2. 捕獲診斷資料
當出現間接性問題時,需要盡可能多地收集資料,而不只是出現問題時的資料。
診斷觸發器
是問題出現時能捕獲資料的基礎。
誤報和漏檢可能導致無法達到預期的結果。
監控伺服器,當達到觸發條件時能收集資料的工具:pt-stalk
確定需要收集什麼樣的資料
在需要的時間段內盡可能地收集所有能收集的資料。
執行時間包括工作時間和等待時間。
用於伺服器內部診斷的重要工具oprofile。
可以使用strace剖析伺服器的系統呼叫。(生產環境中有一定風險)
有一些不可預期性
開銷大使用的是實際時間
對mysqld這樣有大量執行緒場景會產生一些***,導致mysqld執行非常慢
可以使用tcpdump剖析查詢。
可以使用gdb的堆疊跟蹤進行對等分析。(具有侵入性,會暫時造成伺服器停頓)
可以使用show processlist和show innodb status的快照資訊觀察執行緒和事務的狀態進行等待分析。
可以使用pt-collect工具收集資料,一般通過pt-stalk呼叫。
3. 解釋結果資料
如果已經正確設定好觸發條件,並且長時間執行pt-stalk,則只需要等待足夠長的時間來捕獲幾次問題,就能得到大量資料進行篩選。
建議根據兩個目的來檢視:
檢查問題是否真的發生了。
是否有非常明顯的跳躍性變化。
檢視異常的查詢和事務的行為,以及異常伺服器內部行為通常都是最有效的。通過抓取tcp流量或show processlist輸出,可以獲得查詢和事務出現的地方,從而知道使用者對資料庫進行了什麼操作。伺服器內部行為可在oprofile或者gdb的輸出中看到。
檢視異常的查詢和事務的行為,可以顯示是否由於使用伺服器的方式導致的問題:
效能低下的sql查詢
使用不當的索引
設計糟糕的資料庫邏輯架構
通過伺服器的內部行為:
可以清楚伺服器是否有bug
內部的效能和擴充套件性是否有問題
pt-mysql-summary和pt-summary這兩個工具會輸出mysql的狀態和配置資訊,以及作業系統和硬體資訊。
pt-sift是一款快速檢查收集到的樣本資料的工具。
gdb的堆疊追蹤是重要的等待分析的效能瓶頸分析工具:
需要自下而上來看。
將很多資訊聚合在一起來看。
窮人剖析器poor man's profiler:
pt-pmp
如何高效能的使用mysql呢?
1. 設計最優的庫表結構
2. 建立最好的索引並實際應用
3. 設計合理的sql
mysql 檢視 分割槽 Mysql表分割槽狀態查詢
一 查詢mysql表是否為分割槽表 可以檢視表具有哪幾個分割槽 分割槽的方法 分割槽中資料的記錄數等資訊 select partition name,partition method,partition expression,partition description,table rows,subp...
mysql查多少位 如何檢視mysql是幾位的
檢視mysql是幾位的方法 首先開啟cmd 然後切換至mysql的bin目錄 最後執行命令 e mysql bin mysql v 即可。檢視mysql的版本,主要有以下幾個方法 沒有連線到mysql伺服器,就想檢視mysql的版本。開啟cmd,切換至mysql的bin目錄,執行下面的命令即可 e ...
mysql檢視表備註 mysql表中如何檢視備註
mysql表中檢視備註的方法 1 通過 information schema.tables 語句檢視所有表的注釋 2 通過 information schema.tables a left join.語句查詢所有表及字段的注釋等等。mysql 檢視表注釋或字段注釋 檢視所有表的注釋select ta...