MySQL慢查詢日志是MySQL提供的一種日志記錄,用來記錄執行時長超過指定時長的查詢語句,具體指運行時間超過 long_query_time
值的 SQL 語句,則會被記錄到慢查詢日志中。
long_query_time
默認值是 10
,單位是 s
,即默認是 10秒 。默認情況下,MySQL數據庫並不會開啟慢查詢日志,需要手動設置這個參數。
通過慢查詢日志,可以查找出哪些查詢語句的執行效率很低,以便進行優化。一般建議開啟,它對服務器性能的影響微乎其微,但是可以記錄MySQL服務器上執行了很長時間的查詢語句。慢查詢日志可以幫助我們定位mysql性能問題所在。
MySQL慢查詢日志
慢查詢日志相關參數
slow_query_log : 是否啟用慢查詢日志,[1 | 0] 或者 [ON | OFF]
slow_query_log_file : MySQL數據庫(5.6及以上版本)慢查詢日志存儲路徑。
可以不設置該參數,系統則會默認給一個缺省的文件 HOST_NAME-slow.log
long_query_time : 慢查詢的閾值,當查詢時間超過設定的閾值時,記錄該SQL語句到慢查詢日志。
log_queries_not_using_indexes :設置為 ON ,可以捕獲到所有未使用索引的SQL語句(不建議啟用)
log_output : 日志存儲方式。
log_output='FILE',表示將日志存入文件,默認值是'FILE'。
log_output='TABLE',表示將日志存入數據庫,這樣日志信息就會被寫入到 mysql.slow_log 表中。
MySQL數據庫支持同時兩種日志存儲方式,配置的時候以逗號隔開即可,如:log_output='FILE,TABLE'。
日志記錄到系統的專用日志表中,要比記錄到文件耗費更多的系統資源,因此對於需要啟用慢查詢日志,又需要能夠獲得更高的系統性能,那么建議優先記錄到文件。
5.6之前的版本,有些參數名字不一樣:
log-slow-queries : MySQL數據庫(5.6以下版本)慢查詢日志存儲路徑。
開啟日志
立即生效,重啟失效
mysql> set global slow_query_log=ON;
mysql> set global slow_query_log_file='/xxx/mysql-slow.log';
永久生效
修改 my.cnf
:
[mysqld]
slow_query_log = 1
slow_query_log_file = /xxx/mysql-slow.log
long_query_time = 1
# 也可以寫成這種形式
slow-query-log = 1
slow-query-log-file = /xxx/mysql-slow.log
long-query-time = 1
重啟mysql服務。
關閉日志
臨時關閉,重啟失效:
mysql> set global slow_query_log=OFF;
永久關閉,修改 my.cnf
,重啟mysql服務:
[mysqld]
slow_query_log = 0
MySQL慢查詢日志分析
慢查詢日志格式說明
打開慢查詢日志 mysql-slow.log
,內容都是以下格式:
# Time: 2017-11-22T12:22:32.554299Z
# User@Host: www[www] @ [192.168.10.2] Id: 580785559
# Query_time: 24.354270 Lock_time: 0.000238 Rows_sent: 1 Rows_examined: 511156
SET timestamp=1511353352;
SELECT * FROM mo_user WHERE email = 'chxxx@hotmail.com' LIMIT 1;
其中參數說明如下:
- log 記錄的時間:# Time: 2017-11-22T12:22:32.554299Z
- SQL 的執行主機:# User@Host: www[www] @ [192.168.10.2] Id: 580785559
- SQL 的執行信息(執行時間(單位:s),鎖時間,返回結果行數,查詢總行數):# Query_time: 24.354270 Lock_time: 0.000238 Rows_sent: 1 Rows_examined: 511156;
- SQL 執行發生的時間:SET timestamp=1511353352;
- SQL 的執行內容:SELECT * FROM mo_user WHERE email = 'chxxx@hotmail.com' LIMIT 1;
mysqldumpslow
mysqldumpslow 是MySQL自帶的慢查詢日志分析工具(perl腳本)。執行命令 mysqldumpslow --help
,顯示命令參數如下:
Usage: mysqldumpslow [ OPTS... ] [ LOGS... ]
Parse and summarize the MySQL slow query log. Options are
--verbose verbose
--debug debug
--help write this text to standard output
-v verbose
-d debug
-s ORDER what to sort by (al, at, ar, c, l, r, t), 'at' is default
al: average lock time
ar: average rows sent
at: average query time
c: count
l: lock time
r: rows sent
t: query time
-r reverse the sort order (largest last instead of first)
-t NUM just show the top n queries
-a don't abstract all numbers to N and strings to 'S'
-n NUM abstract numbers with at least n digits within names
-g PATTERN grep: only consider stmts that include this string
-h HOSTNAME hostname of db server for *-slow.log filename (can be wildcard),
default is '*', i.e. match all
-i NAME name of server instance (if using mysql.server startup script)
-l don't subtract lock time from total time
參數說明:
-
-v、--verbose : 在詳細模式下運行,打印有關該程序的更多信息。
-
-d、--debug : 在調試模式下運行。
-
--help : 顯示幫助信息並退出程序
-
-s [sort_type] : sort_type 是信息排序的依據
al:average lock time,按平均等待鎖的時間排序
ar:average rows sent,按平均發給客戶端的行總數排序
at:average query time,按平均查詢時間排序
c:count,按出現總次數排序
l:lock time,按等待鎖的時間排序
r:rows sent,按掃描的行總數排序
t:query time,按累計總耗費時間排序 -
-r : 倒序信息排序
-
-t NUM: 只顯示前 n 個查詢,降序
-
-a : 不把數字抽象為'N',不把字符串抽象為'S'
-
-n NUM : 「abstract numbers with at least n digits within names」
-
-g PATTERN : 根據字符串篩選慢查詢日志,可寫正則匹配,大小寫不敏感。
-
-h HOSTNAME : 根據服務器名稱選擇慢查詢日志
-
-i NAME : 根據服務器 MySQL 實例名稱選擇慢查詢日志
-
-l : 不要將總時間減去鎖定時間
mysqldumpslow
分析的結果如下:
- Count : 出現次數(Count)
- Time : 執行最長時間(Time) 和 累計總耗費時間(Time)
- Lock : 等待鎖的時間(Lock)
- Rows : 發送給客戶端的行總數(Rows) 和 掃描的行總數(Rows)
- root[root]@localhost : 用戶
- SHOw FULL ... : SQL語句本身(抽象了格式, 比如 limit 1, 20 用 limit N,N 表示。'N'表示數字,'S'表示字符串)。
例子:
返回記錄數最多的10個SQL
mysqldumpslow -s r -t 10 mysql-slow.log
mysqlsla
mysqlsla是 hackmysql.com 推出的一款日志分析工具(該網站還維護了 mysqlreport
, mysqlidxchk
等比較實用的mysql工具)
整體來說, 功能非常強大。數據報表,非常有利於分析慢查詢的原因, 包括執行頻率, 數據量, 查詢消耗等。
但是,hackmysql.com官方已經在2015年1月份放棄了對mysqlsla的維護。
安裝
解決依賴關系
# yum install perl-DBI perl-DBD-MySQL
可能會遇到的問題:Can't locate ExtUtils/MakeMaker.pm
,解決如下:
# yum install perl-ExtUtils-CBuilder perl-ExtUtils-MakeMaker
可能會遇到的問題:Can't locate Time/HiRes.pm in @INC
,解決如下:
# yum install perl-Time-HiRes
下載mysqlsla
當前 mysqlsla 的最新版本為 2.03
,到官網下載(官方鏈接已經失效),可以去這個 有效下載地址 下載。
編譯安裝
# tar xvfz mysqlsla-2.03.tar.gz
# cd mysqlsla-2.03
# perl Makefile.PL
# make
# make install
使用
# mysqlsla -lt slow mysql-slow.log
或者
# mysqlsla -lt slow mysql-slow.log -sf "+SELECT" -db dbName -top 10 -sort t_sum
參數意義 :
- -lt :表示日志類型,有: slow, general, binary, msl, udl
- -sf :[+-][TYPE],包括|不包括,過濾sql語句的類型 [TYPE]有 SELECT, CREATE, DROP, UPDATE, INSERT,例如 "+SELECT,INSERT",不出現的默認是 - ,即不包括。
- -db :要處理哪個庫的日志。
- -top :表示取按規則排序的前多少條。
- -sort :按某種規則排序,t_sum 按總時間排序, c_sum 按總次數排序。c_sum_p : sql語句執行次數占總執行次數的百分比。
對慢查詢日志文件的分析,最簡化的調用方式如下:
# mysqlsla -lt slow [SlowLogFilePath] > [ResultFilePath]
格式說明如下:
- 總查詢次數 (queries total), 去重后的sql數量 (unique)
- 輸出報表的內容排序方式(sorted by)
- 最重大的慢sql統計信息, 包括平均執行時間, 等待鎖時間, 結果行的總數, 掃描的行總數。
- Count: sql的執行次數及占總的slow log數量的百分比.
- Time:執行時間, 包括總時間, 平均時間, 最小, 最大時間, 時間占總慢sql時間的百分比.
- 95% of Time:去除最快和最慢的sql, 覆蓋率占95%的sql的執行時間.
- Lock Time:等待鎖的時間.
- 95% of Lock :95%的慢sql等待鎖時間.
- Rows sent:結果行統計數量, 包括平均, 最小, 最大數量.
- Rows examined: 掃描的行數量.
- Database:屬於哪個數據庫
- Users:哪個用戶,IP, 占到所有用戶執行的sql百分比
- Query abstract:抽象后的sql語句
- Query sample:sql語句個例
pt-query-digest
percona-toolkit 工具介紹
percona-toolkit
是一組高級命令行工具的集合,用來執行各種通過手工執行非常復雜和麻煩的mysql和系統任務。這些任務包括:
- 檢查master和slave數據的一致性
- 有效地對記錄進行歸檔
- 查找重復的索引
- 對服務器信息進行匯總
- 分析來自日志和tcpdump的查詢
- 當系統出問題的時候收集重要的系統信息
Percona Toolkit整個工具箱提供了非常多實用的工具,具體的使用方法可以參看 官方文檔
percona-toolkit安裝
安裝 percona-toolkit
非常簡單,到 官網 下載 .tar.gz 包:
# wget percona.com/get/percona-toolkit.tar.gz
# tar -zxvf percona-toolkit-2.2.5.tar.gz
然后依次執行下面的命令:
# perl Makefile.PL
# make
# make install
默認的會被安裝在 /usr/local/bin
目錄下。執行 man percona-toolkit
可以查看安裝了哪些工具。
運行工具可能會遇到下面的錯誤:
這是因為缺少相應包,.pm包實際上是perl的包,運行下面的命令安裝即可:
yum install -y perl-Time-HiRes
如果安裝過程中出現 Error Downloading Packages
錯誤,嘗試 yum clean all
后再安裝。使用其Percona Toolkit中其他工具也可能會遇到類似的問題,按照提示安裝相應的perl包就可以了。
問題:Can't locate Digest/MD5.pm in @INC
解決:# yum install perl-Digest-MD5
問題:Can't locate ExtUtils/MakeMaker.pm in @INC
解決:# yum install perl-ExtUtils-CBuilder perl-ExtUtils-MakeMaker
pt-query-digest使用
pt-query-digest
可以從普通MySQL日志,慢查詢日志以及二進制日志中分析查詢,甚至可以從 SHOW PROCESSLIST;
和MySQL協議的tcpdump中進行分析,如果沒有指定文件,它從標准輸入流(STDIN)中讀取數據。
最簡單的用法如下:
# pt-query-digest mysql-slow.log
輸出信息大致如下:
整個輸出分為三大部分:
整體概要(Overall)
這個部分是一個大致的概要信息(類似loadrunner給出的概要信息),通過它可以對當前MySQL的查詢性能做一個初步的評估,比如各個指標的最大值(max),平均值(min),95%分布值,中位數(median),標准偏差(stddev)。
這些指標有查詢的執行時間(Exec time),鎖占用的時間(Lock time),MySQL執行器需要檢查的行數(Rows examine),最后返回給客戶端的行數(Rows sent),查詢的大小。
查詢的匯總信息(Profile)
這個部分對所有 "重要" 的查詢(通常是比較慢的查詢)做了個一覽表:
每個查詢都有一個Query ID,這個ID通過Hash計算出來的。pt-query-digest
是根據這個所謂的Fingerprint來group by的。舉例下面兩個查詢的Fingerprint是一樣的都是 select * from table1 where column1 = ?
,工具箱中也有一個與之相關的工具 pt-fingerprint
。
select * from table1 where column1 = 2
select * from table1 where column1 = 3
- Rank整個分析中該“語句”的排名,一般也就是性能最常的。
- Response time “語句”的響應時間以及整體占比情況。
- Calls 該“語句”的執行次數。
- R/Call 每次執行的平均響應時間。
- V/M 響應時間的差異平均對比率。
在尾部有一行輸出,顯示了其他2個占比較低而不值得單獨顯示的查詢的統計數據。
詳細信息
這個部分會列出Profile表中每個查詢的詳細信息:(默認是按照總的Exec time排序,降序)
包括Overall中有的信息、查詢響應時間的分布情況以及該查詢 "入榜" 的理由,最底下會顯示該查詢SQL語句(真實顯示,非抽象格式)。
pt-query-digest 還有很多復雜的操作,這里就不一一介紹了。比如:從PROCESSLIST中查詢某個MySQL中最慢的查詢:
# pt-query-digest –processlist h=host1
從tcpdump中分析:
# tcpdump -s 65535 -x -nn -q -tttt -i any -c 1000 port 3306 > mysql.tcp.txt
# pt-query-digest --type tcpdump mysql.tcp.txt
從一台機器上將 slow log
保存到另外一台機器上待稍后詳細分析:
# pt-query-digest --review h=host2 --no-report slow.log
還可以跟一些過濾條件。詳見 官方文檔
另外結合一些第三方工具還能生成相應的報表,可以 參考這里
建議 :當 slow log
很大的時候最好還是將日志文件移到其他機器上進行分析,避免分析時過度消耗該服務器資源。