這是《高性能 MySQL(第三版)》第三章的讀書筆記。php
關於服務,常見的問題有:html
經過性能剖析(profiling)分析服務器的性能並找出花費時間最多的地方,有助於解決上述問題。mysql
性能一般能夠認爲就是響應時間(Latency,延遲),而性能優化就是減小響應時間。nginx
要想優化性能,首先須要知道性能的瓶頸在哪裏。這就須要用到測試了。c++
每種語言都有專門的測試程序,對於 PHP,可使用的有:git
經過分析服務器負載,定位須要優化的單條查詢。github
MySQL 中,慢查詢日誌是開銷最低、精度最高的測量查詢時間的工具。運行時間超過 long_query_time 值語句會被記錄到慢查詢日誌中。long_query_time 單位是秒,默認值爲 10,能夠設置爲 0 來捕獲全部的查詢。慢查詢日誌須要手動開啓,開啓後會略微影響性能。慢查詢日誌能夠寫入文件或數據庫,但寫入到數據庫時會影響性能且時間粒度退化爲秒級。web
MySQL 中還有另一種查詢日誌,叫通用日誌,但可用信息太少且資源消耗大,基本不用。算法
慢查詢日誌相關參數以下,使用能夠參考 這裏:sql
分析慢查詢日誌可使用 MySQL 自帶的 mysqldumpslow 工具。要用慢查詢日誌生成分析報告可使用 pt-query-digest 工具。
定位到須要優化的單條查詢後,開始優化。
都廢棄了,別研究了。
–使用前先經過 have_profiling 參數查看當前 MySQL是否支持 profile:–
mysql> select @@have_profiling; +------------------+
| @@have_profiling | +------------------+
| YES | +------------------+
1 row in set, 1 warning (0.01 sec)
mysql> show warnings; +---------+------+---------------------------------------------------------------------------+
| Level | Code | Message | +---------+------+---------------------------------------------------------------------------+
| Warning | 1287 | '@@have_profiling' is deprecated and will be removed in a future release. | +---------+------+---------------------------------------------------------------------------+
1 row in set (0.00 sec)
–默認禁用,能夠經過服務器變量在會話級別啓用:–
mysql> SET profiling = 1;
Performace Schema 是目前 MySQL(5.7 及以上版本)主推的性能測試工具,默認開啓。首次安裝 MySQL 後,你會發現其默認安裝了幾個數據庫,其中的 performace_schema 就是用於配置 Performace Schema 的。
SHOW STATUS 命令返回一些服務器級別的全局計數器或某個會話級別的計數器。能夠顯示活動頻繁程度,可是沒法給出消耗的時間。
mysql> show global status; +-----------------------------------------------+--------------------------------------------------+
| Variable_name | Value | +-----------------------------------------------+--------------------------------------------------+
| Aborted_clients | 275 | | Aborted_connects | 80872 |
| Binlog_cache_disk_use | 0 | ... | Threads_running | 1 |
| Uptime | 6661773 |
| Uptime_since_flush_status | 6661773 | | validate_password_dictionary_file_last_parsed | 2018-01-31 15:35:09 |
| validate_password_dictionary_file_words_count | 0 | +-----------------------------------------------+--------------------------------------------------+
355 rows in set (0.03 sec)
應用偶爾停頓、數據庫間歇性的慢查詢的可能緣由有:
解決間歇性問題有常見的套路和工具,定位好問題才能進行以後的操做。
SHOW STATUS 或 SHOW SESSION STATUS 顯示當前會話級別的信息,SHOW GLOBAL STATUS 顯示服務器級別的信息。完整差別能夠參考 SHOW GLOBAL STATUS vs SHOW STATUS。
以較高的頻率執行 SHOW GLOBAL STATUS 命令捕獲數據,問題出現時能夠經過某些計數器(Threads_running、Threads_connected、Questions、Queries)的「尖刺」和「凹陷」來發現問題。SHOW GLOBAL STATUS 命令的用法簡單且執行時不須要特殊權限(登陸數據庫的用戶均可以使用)、對服務器影響小。
下面示例經過 -i1
選項每秒捕捉一次數據,輸出給 awk 計算並輸出每秒的查詢數、Threads_connected、Threads_running:
[root@VM_120_242_centos ~]# mysqladmin -uroot -p ext -i1 | awk '/Queries/{q=$4-qp;qp=$4} /Threads_connected/{tc=$4} /Threads_running/{printf "%d %d %d\n", q, tc, $4}' Enter password: 1554866 1 1 1 1 1 1 1 1
下面示例經過 -i1
選項每秒捕捉一次數據,經過 -r
選項展現差值,輸出給 awk 計算並輸出每秒的查詢數:
# mysqladmin -uroot -p ext -i1 -r | awk '/Queries/{q=$4} /Threads_connected/{tc=$4} /Threads_running/{printf "%d %d %d\n", q, tc, $4}'
Enter password:
1554856 1 1
1 0 0
1 0 0
1 0 0
不停的捕獲 SHOW PROCESSLIST 的輸出,能夠觀察是否有大量線程處於不正常狀態或有不正常特徵。例如查詢不多會長時間處於「statictics」狀態。
示例,經過命令尾部使用 \G 替換分號能夠垂直輸出結果,經過 sort|uniq|sort
命令能夠計算某個列值出現的次數:
[root@VM_120_242_centos ~]# mysql -uroot -p -e 'SHOW PROCESSLIST\G' | grep State: | sort | uniq -c | sort -rn
Enter password:
2 State:
1 State: starting
除了經過命令行外,也能夠直接查詢 INFORMATION_SCHEMA 數據庫中的 PROCESSLIST 表。
須要開啓慢查詢日誌,並在全局級別設置 long_query_time 爲 0,而後重置全部鏈接以使新的全局設置生效。
好的工具能夠幫助診斷問題,不然就要去幾百 GB 的日誌文件中查找問題。下面示例的一行代碼能夠根據 MySQL 每秒將當前時間寫入日誌中的模式統計每秒的查詢數量:
awk '/^# Time:/{print $3, $4, c; c=0}/^# User/{c++}' slow-query.log
建議剛開始診斷問題時,先使用 SHOW STATUS 和 SHOW PROCESSLIST。這兩種方法開銷低,且能夠經過 shell 或反覆查詢來收集數據。分析慢查詢日誌則比較困難。
診斷間歇性問題,須要收集儘量多的數據。須要兩個工具:
觸發器須要避免「誤報」和「漏檢」。
一般將觸發器閾值調整爲正常狀況的一倍左右。好比 Threads_running 在正常狀況下是 10,則觸發器的閾值能夠設置爲 20。對於 Threads_connected 若是正常值爲 150,則閾值能夠是 300。
另外,還須要設置持續時間。好比 Threads_running 連續 3 秒鐘超過 20,則認爲是異常狀況。可使用「pt-stalk」工具。
肯定診斷觸發器後,能夠開啓進程收集數據。數據應該儘量多,包括系統狀態、CPU 利用率、磁盤使用率和可用空間、內存利用率、ps 命令的輸出採樣,以及從 MySQL 得到的信息,包括 SHOW STATUS、SHOW INNODB STATUS、SHOW PROCESSLIST。
Linux 上可用的服務器內部診斷工具備 oprofile、strace(生產環境中使用有風險)。要剖析查詢可用 tcpdump。
能夠經過 GDB 堆棧跟蹤分析等待緣由。跟蹤時先啓動 GDB,而後附加(attach)到 mysqld 進程,將全部線程的堆棧都存儲起來。而後利用腳本彙總相似的堆棧信息,再利用 sort|uniq|sort 排序。
INFORMATION_SCHEMA 庫中的表,存儲了各個數據庫的信息及全部活動的統計信息,能夠得知哪一個數據庫的哪一個表、哪一個索引使用的最頻繁。
表索引的信息。SHOW INDEX FROM schemaname.tablename; 命令從這個表獲取結果。
mysql> SHOW INDEX FROM szhuizhong.users; +-------+------------+---------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | +-------+------------+---------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| users | 0 | PRIMARY | 1 | UserID | A | 1460 | NULL | NULL | | BTREE | | |
| users | 0 | Account_index | 1 | Account | A | 1460 | NULL | NULL | | BTREE | | | | users | 1 | CorpID | 1 | FromID | A | 2 | NULL | NULL | YES | BTREE | | | +-------+------------+---------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 3 rows in set (0.00 sec)
要解決問題,首先要搞清楚問題。全部的查詢記錄都要記錄到日誌中,而後用 pt-query-digest 工具生成系統級別的剖析報告。