第一步.開啟 MySQL 慢查詢
方式一、修改配置文件
Windows:配置文件為 my.ini,一般在 MySQL 安裝目錄下或者 c:\Windows 下。
Linux:配置文件為 my.cnf ,一般在 /etc 下。
在 my.ini 增加下面代碼:
[mysqld]
long_query_time=2
#5.5以前版本配置如下選項
log-slow-queries="mysql_slow_query.log"
#5.5及以上版本配置如下選項
slow-query-log=On
slow_query_log_file="mysql_slow_query.log"
log-query-not-using-indexes
第一句:定義超過多少秒的查詢算是慢查詢,這里定義的是2秒
第二句:定義慢查詢日志的路徑(注意如果是 Linux 或 Mac 系統要考慮權限問題)
第三句:記錄下沒有使用索引的query
方式二、通過命令行開啟慢查詢
上面的配置需要重啟 mysql server 進程 mysqld 才會生效。但很多時候,尤其是產品生產環境,不希望每次修改都要重新啟動mysql服務器,而是希望能在某些特定時間記錄。MySQL5.1 之后為我們提供了靈活的運行時控制,使得你不必重新啟動 mysql 服務器,也能選擇性地記錄或不記錄某些 slow queries。
MySQL5.1中,提供了全局變量 slow_query_log、slow_query_log_file,可以靈活地控制enable/disable慢查詢。同時可以通過 long_query_time 設置慢查詢時間
注意:設置了全局變量 slow_query_log ,則變量 log_slow_queries 也會隱性地跟著改變
mysql>set global slow_query_log=ON
不幸的是,在 MySQL5.1 之前并沒有提供類似的全局變量來靈活控制,但是我們可以通過將long_query_time 設置得足夠大來避免記錄某些查詢語句。比如
mysql>set global long_query_time = 3600;
mysql>set global log_querise_not_using_indexes = ON;
MySQL5.0 在不關閉服務的情況下,希望不記錄日志的辦法是讓日志文件成為 /dev/null 的符號鏈接(symbolic link)。注意:你只需要在改變后運行 flush logs 以確定MySQL釋放當前的日志文件描述符,重新把日志記錄到/dev/null。
和 MySQL5.0 不同, MySQL5.1 后可以在運行時改變日記行為,將日志記錄到數據庫表中。只要將 MySQL 全局變量 log_output 設置為 table 即可。MySQL 會將日志分別記錄到mysql.gengera_log 和 mysql.slow_log 兩張表中。但是,推薦的做法是將日志記錄在日記文件中。
mysql> show variables like ‘log_output’\G
Variable_name: log_output
Value: FILE
mysql>set global log_output=’table’;
缺陷與審記
如果開啟了 log_queries_not_using_indexes 選項,slow query 日志會充滿過多的垃圾日志記錄,這些快且高效的全表掃描查詢(表小)會沖掉真正有用的slow queries記錄。比如 select * from category 這樣的查詢也會被記錄下來。
通過microslow-patch補丁可使用更細的時間粒度,和記錄所有執行過的sql語句。不過,使用這個補訂不得不自己編譯MySQL,出于穩定性考濾,我們推薦在開發測試環境,可以打上這個補丁,享受這個補丁帶來的便利。在運營環境盡量不要這么做…
第二步.驗證慢查詢是否開啟
執行如下SQL語句來查看 mysql 慢查詢的狀態,結果會把是否開啟慢查詢、慢查詢的秒數、慢查詢日志等信息打印在屏幕上。
/*查看慢查詢時間 */
show variables like "long_query_time";默認10s
/*查看慢查詢配置情況 */
show status like "%slow_queries%";
/*查看慢查詢日志路徑 */
show variables like "%slow%";
第三步.執行一次慢查詢操作
其實想要執行一次有實際意義的慢查詢比較困難,因為在自己測試的時候,就算查詢有20萬條數據的海量表,也只需要零點幾秒。我們可以通過如下語句代替:
SELECT SLEEP(10);
第四步.查看慢查詢的數量
通過如下 sql 語句,來查看一共執行過幾次慢查詢:
show global status like '%slow%';
mysql日志的配置:
注意:這些日文件在mysql重啟后才會生效
#記錄所有sql語句
log=/usr/local/mysql/data/mysql.log
#記錄數據庫啟動關閉信息,以及運行過程中產生的錯誤信息
log-error=/usr/local/mysql/data/myerror.log
# 記錄除 select 語句之外的所有 sql 語句到日志中,可以用來恢復數據文件
log-bin=/usr/local/mysql/bin
#記錄查詢慢的sql語句
log-slow-queries=/usr/local/mysql/data/slow.log
#慢查詢時間
long_query_time=2
第五步.分析慢查詢日志
方式一.通過工具分析
MySQL 自帶了 mysqldumpslow 工具用來分析 slow query 日志,除此之外,還有一些好用的開源工具。比如MyProfi、mysql-log-filter,當然還有 mysqlsla。
以下是 mysqldumpslow 常用參數說明,詳細內容可用 mysqldumpslow -help 查詢。
-s,表示按照何種方式排序,c、t、l、r分別是按照記錄次數、時間、查詢時間、返回的記錄數來排序(從大到小),ac、at、al、ar表示相應的倒序。
-t,是top n的意思,即為返回前面多少條數據。
-g,后邊可以寫一個正則匹配模式,大小寫不敏感。
接下來就是用MySQL 自帶的慢查詢工具 mysqldumpslow 分析了(該工具位于 MySQL 的bin 目錄下),我這里的日志文件名字是host-slow.log。
列出記錄次數最多的10個sql語句
mysqldumpslow -s c -t 10 host-slow.log
列出返回記錄集最多的10個sql語句
mysqldumpslow -s r -t 10 host-slow.log
按照時間返回前10條里面含有左連接的sql語句
mysqldumpslow -s t -t 10 -g "left join" host-slow.log
使用mysqldumpslow命令可以非常明確的得到各種我們需要的查詢語句,對MySQL查詢語句的監控、分析、優化起到非常大的幫助。
方式二.直接分析mysql慢查詢日志
日志部分內容如下:
# Time: 170502 17:38:54
# User@Host: root[root] @ localhost [127.0.0.1]
# Query_time: 3.794217 Lock_time: 0.000000 Rows_sent: 1 Rows_examined: 4194304
SET timestamp=1350466734;
select * from wei where text='orange';
# Time: 170502 17:46:22
# User@Host: root[root] @ localhost [127.0.0.1]
# Query_time: 3.819219 Lock_time: 0.000000 Rows_sent: 0 Rows_examined: 4194304
SET timestamp=1350467182;
select * from wei where text='xishizhaohua';
其實定位到慢查詢語句就已經完成了一大步了,執行 explain 或者 desc 命令查看慢查詢語句,如下圖:
問題很明顯,解決方式也很明顯-------建索引。
mysql> create index text_index on wei(text);
Query OK, 4194304 rows affected (1 min 58.07 sec)
Records: 4194304 Duplicates: 0 Warnings: 0
然后再執行查詢操作,用時明顯少了很多。
mysql> select * from wei where text='orange';
+---------+--------+
| id | text |
+---------+--------+
| 4103519 | orange |
+---------+--------+
1 row in set (0.33 sec)
Slow Query 日志雖然幫你記錄了執行過的SQL語句。但它不是萬能的,意義可能沒有你想象的那么大。它只告訴了你哪些語句慢,但是為什么慢?具體原因,還是需要你自己去分析,不斷的調試。也許你只需要換一條更有效的sql語句,也許你只需簡單地增加一個索引,但也有可能你需要調整你應用程序的設計方案。比如上面那條語句很明顯,它檢查了400多萬行數據。不幸的是,并不是每條語句都這么明顯。也許還有別的原因,比如:
- 鎖表了,導致查詢處于等態狀態。lock_time顯示了查詢等待鎖被翻譯的時間
- 數據或索引沒有被緩存。常見于第一次啟動服務器或者服務器沒有調優
- 備份數據庫,I/O變慢
- 同時運行了其它的查詢,減少了當前查詢
所以,不要過于關注日志文件某條記錄,而應該理性地審查,找出真正的原因。如經常出現的 slow query 需要特別注意。如果個別出現,則做一些常規檢查即可。推薦大家統計并形成基準報告,進行比較排除,如此肯定比胡亂瞎撞有用。希望大家不要在這部分過于浪費時間與精力。