1. 程式人生 > >MySQL 監控指標

MySQL 監控指標

含義 long 標準 utili time where 求次數 receive 縮小

為了排查問題,對數據庫的監控是必不可少的,在此介紹下 MySQL 中的常用監控指標。

技術分享圖片

簡介

MySQL 有多個分支版本,常見的有 MySQL、Percona、MariaDB,各個版本所對應的監控項也會有些區別,在此僅介紹一些通用的監控項。

通常,監控項的源碼是在 mysql/mysqld.cc 文件中定義,其內容如下所示。

SHOW_VAR status_vars[]= {
    {"Aborted_clients",          (char*) &aborted_threads,        SHOW_LONG},
    {"Aborted_connects",         (char*) &aborted_connects,       SHOW_LONG},
    {"Acl",                      (char*) acl_statistics,          SHOW_ARRAY},
    // ... ...
};

監控

對於數據庫,通常可以主動監控以下四個與性能及資源利用率相關的指標:

  • 查詢吞吐量
  • 查詢執行性能
  • 連接情況
  • 緩沖池使用情況

吞吐量

在 MySQL 中有各種針對不同命令的統計,其監控項指標以 Com_XXX 方式命名,其中比較常用的統計項包括了 TPS/QPS。

而 MySQL 與 QPS 相關的包括了三個監控項,分別為 Queries、Questions、Com_select,一般會采用 Com_select 作為采集項;對於 TPS,一般認為是 Com_insert + Com_update + Com_delete 三個統計項的和。

Queries 和 Questioins 區別

如下是 Server Status Variables 中對這兩個值的介紹。

Queries : The number of statements executed by the server. This variable
includes statements executed within stored programs, unlike the Questions
variable. It does not count COM_PING or COM_STATISTICS commands.

Questions : The number of statements executed by the server. This includes
only statements sent to the server by clients and not statements executed
within stored programs, unlike the Queries variable. This variable does
not count COM_PING, COM_STATISTICS, COM_STMT_PREPARE, COM_STMT_CLOSE, or
COM_STMT_RESET commands.

也就是說,如果不使用 prepared statements ,那麽兩者的區別是 Questions 會將存儲過程作為一個語句;而 Queries 會統計存儲過程中的各個執行的語句。

mysql> SHOW STATUS LIKE "questions";        ← 查看本連接執行的查詢SQL數
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Questions     | 2     |
+---------------+-------+
1 row in set (0.00 sec)

mysql> SHOW STATUS LIKE "queries";
+---------------+----------+
| Variable_name | Value    |
+---------------+----------+
| Queries       | 21241470 |
+---------------+----------+
1 row in set (0.00 sec)

上述的 questions 是會話級別的,當然可以通過 global 查看全局的變量。

另外,MySQL 會在執行 SQL 之前開始增加上述的統計計數;而當前正在執行的 SQL 數量則可以通過 threads_running 查看。

總結

Questions        已執行的由客戶端發出的語句
Com_select       執行SELECT語句的數量,通常也就是QPS
Writes           Com_insert+Com_update+Com_delete,也就是TPS

執行性能

目前,有幾種方式可以用來查看 MySQL 的執行性能問題,可以參考如下。

performance_schema

在 events_statements_summary_by_digest 表中保存了許多關鍵指標,均以微秒為單位,該表會忽略數值、規範化空格與大小寫。

如果要以微秒為單位查看各個 database 的平均運行時間,或者出現的錯誤語句總數,可以通過如下方式查看:

mysql> SELECT schema_name, SUM(count_star) count,        ROUND((SUM(sum_timer_wait)/SUM(count_star))/1000000) AS avg_microsec        FROM performance_schema.events_statements_summary_by_digest
       WHERE schema_name IS NOT NULL GROUP BY schema_name;

mysql> SELECT schema_name, SUM(sum_errors) err_count        FROM performance_schema.events_statements_summary_by_digest        WHERE schema_name IS NOT NULL GROUP BY schema_name;

sys

sys 存儲引擎默認在 5.7.7 中添加,對於 5.6 可以手動安裝,詳細可以參考 github - sys schema 。

慢查詢

MySQL 提供了一個 Slow_queries 計數器,當查詢的執行時間超過 long_query_time 參數指定的值之後,該計數器就會增加,默認設置為 10 秒。

mysql> SHOW VARIABLES LIKE ‘long_query_time‘;
+-----------------+-----------+
| Variable_name   | Value     |
+-----------------+-----------+
| long_query_time | 10.000000 |
+-----------------+-----------+
1 row in set (0.00 sec)

mysql> SET GLOBAL long_query_time = 5;
Query OK, 0 rows affected (0.00 sec)

需要註意的是,需要關閉會話然後重新連接之後,才能使該參數生效。

總結

Slow_queries         慢查詢的數量

其它的一些比較適合發現性能問題後用於排查。

連接情況

監控客戶端連接情況相當重要,因為一旦可用連接耗盡,新的客戶端連接就會遭到拒絕,MySQL 默認的連接數限制為 151,可通過下面的方法在配置文件中進行設置。

[mysqld]
max_connections = 200

通過如下方法查詢和臨時設置。

mysql> SHOW VARIABLES LIKE ‘max_connections‘;
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| max_connections | 151   |
+-----------------+-------+
1 row in set (0.00 sec)

mysql> SET GLOBAL max_connections = 200;
Query OK, 0 rows affected (0.00 sec)

通常 Linux 可以處理 500~1000 個連接,如果 RAM 資源足夠,可處理 1W+ 個連接,而 Windows 由於采用 Posix 兼容層,能處理的連接數一般不超過 2048 個。

監控連接使用率

如果采用每個連接一個線程的方式,可以通過 Threads_connected 查看,監控該指標與先前設置的連接限制,可以確保服務器擁有足夠的容量處理新的連接。

另外,通過 Threads_running 指標,可以查看正在處理請求的線程,可以用來判斷那些連接被占用但是卻沒有處理任何請求。

如果達到 max_connections 就會拒絕新的連接請求,Connection_errors_max_connections 指標就會開始增加,同時,追蹤所有失敗連接嘗試的 Aborted_connects 指標也會開始增加。

另外,通過 Connection_errors_internal 這個指標,可以用來監控來自服務器本身導致的錯誤,例如內存不足。

總結

Threads_connected                   已經建立的連接
Threads_running                     正在運行的連接
Connection_errors_internal          由於服務器內部本身導致的錯誤
Aborted_connects                    嘗試與服務器建立連接但是失敗的次數
Connection_errors_max_connections   由於到達最大連接數導致的錯誤

緩沖池使用情況

InnoDB 使用一片內存區域作為緩沖區,用來緩存數據表與索引數據,緩沖區太小可能會導致數據庫性能下滑,磁盤 I/O 攀升。

默認值一般是 128MiB,建議將其設置為物理內存的 80%;不過需要註意的是,InnoDB 可能會使用超過緩沖池 10%,如果耗盡內存,則會使用分頁,從而使數據庫性能受損。

SHOW GLOBAL VARIABLES LIKE "innodb_buffer_pool_chunk_size";
SHOW GLOBAL VARIABLES LIKE "innodb_buffer_pool_instances";

如果 innodb_buffer_pool_chunk_size 查詢沒有返回結果,則表示在你使用的 MySQL 版本中此參數無法更改,其值為 128 MiB,實際參數為 innodb_buffer_pool_size 。

在服務器啟動時,你可以這樣設置緩沖池的大小以及實例的數量:

$ mysqld --innodb_buffer_pool_size=8G --innodb_buffer_pool_instances=16

監控指標

Innodb_buffer_pool_read_requests 記錄了讀取請求的數量,而 Innodb_buffer_pool_reads 記錄了緩沖池無法滿足,因而只能從磁盤讀取的請求數量,也就是說,如果 Innodb_buffer_pool_reads 的值開始增加,意味著數據庫性能大有問題。

緩存的使用率和命中率可以通過如下方法計算:

(Innodb_buffer_pool_pages_total - Innodb_buffer_pool_pages_free) /
    Innodb_buffer_pool_pages_total * 100%

(Innodb_buffer_pool_read_requests - Innodb_buffer_pool_reads) /
    Innodb_buffer_pool_read_requests * 100%

如果數據庫從磁盤進行大量讀取,而緩沖池還有許多閑置空間,這可能是因為緩存最近才清理過,還處於預熱階段。

總結

Innodb_buffer_pool_pages_total          BP中總頁面數
Buffer pool utilization                 BP中頁面的使用率
Innodb_buffer_pool_read_requests        BP的讀請求
Innodb_buffer_pool_reads                需要讀取磁盤的請求數

響應時間

“響應時間” (Response Time, RT) 在數據庫應用中,尤其是 OLTP 的場景,非常重要,但官方版本中一直沒有加上這個統計功能。開始使用的是 tcpdump+mk-query-digest,再後來 tcprstat,很快 Percona 提供了響應時間統計插件。

對於 MariaDB 也存在類似的方式,可以通過如下的方式安裝、測試。

----- 1. 查看是否存在插件
$ ls /opt/mariadb/lib/plugin | grep response
query_response_time.so

----- 2. 安裝插件
mysql> INSTALL PLUGIN query_response_time_audit SONAME ‘query_response_time.so‘;
Query OK, 0 rows affected (0.00 sec)
mysql> INSTALL PLUGIN query_response_time SONAME ‘query_response_time.so‘;
Query OK, 0 rows affected (0.00 sec)

----- 3. 打開統計功能
mysql> SET GLOBAL query_response_time_stats = ‘ON‘;
Query OK, 0 rows affected (0.00 sec)
mysql> SET GLOBAL query_response_time_flush = ‘ON‘;
Query OK, 0 rows affected (0.00 sec)

----- 4. 查看統計值
mysql> SHOW QUERY_RESPONSE_TIME;
mysql> SELECT * FROM information_schema.query_response_time;
+----------------+-------+----------------+
| Time           | Count | Total          |
+----------------+-------+----------------+
|       0.000001 |     0 |       0.000000 |
|       0.000010 |     0 |       0.000000 |
|       0.000100 |     1 |       0.000089 |
|       0.001000 |    14 |       0.010173 |
|       0.010000 |     0 |       0.000000 |
|       0.100000 |     0 |       0.000000 |
|       1.000000 |     0 |       0.000000 |
|      10.000000 |     0 |       0.000000 |
|     100.000000 |     0 |       0.000000 |
|    1000.000000 |     0 |       0.000000 |
|   10000.000000 |     0 |       0.000000 |
|  100000.000000 |     0 |       0.000000 |
| 1000000.000000 |     0 |       0.000000 |
| TOO LONG       |     0 | TOO LONG       |
+----------------+-------+----------------+
14 rows in set (0.00 sec)

默認的時間統計區間是按照基數 10 增長的,也就是說默認的區間如下:

(0;10^-6], (10^-6;10^-5], (10^-5;10^-4], ..., (10^-1;10^1], (10^1; 10^2], ...

可以通過修改參數 query_response_time_range_base 來縮小時間區間,默認該是 10,實際的統計時間區間如上,可以修改為 2,則區間如下:

(0;2^-19], (2^-19;2^-18], (2^-18;2^-17], ..., (2^-1; 2^1], (2^1; 2^2], ...

第一個區間總是最接近 0.000001 的區間開始;最後區間是到最接近且小於 10000000 處結束。

當然,有些比較從網上摘錄的不錯 SQL,可以根據自己需求修改。

SELECT
    case TRIM(time)
        when ‘0.000001‘ then ‘<  1us‘
        when ‘0.000010‘ then ‘< 10us‘
        when ‘0.000100‘ then ‘<100us‘
        when ‘0.001000‘ then ‘<  1ms‘
        when ‘0.010000‘ then ‘< 10ms‘
        when ‘0.100000‘ then ‘<100ms‘
        when ‘1.000000‘ then ‘<   1s‘
        when ‘10.000000‘ then ‘<  10s‘
        when ‘100.000000‘ then ‘<100s‘
        else ‘>100s‘
    END as `RT area`,
    CONCAT(ROUND(100*count/query_count,2),"%") as percent,
    count
FROM(
    SELECT
        c.count,
        c.time,
        (
            SELECT SUM(a.count)
            FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as a
            WHERE a.count != 0
        ) as query_count
    FROM INFORMATION_SCHEMA.QUERY_RESPONSE_TIME as c
    WHERE c.count > 0
) d;

其它監控項

除了上述的監控項,常見的還有如下常用的方法。

1. 是否可用

可以使用如下幾條命令來查看當前 MySQL 服務是否處於運行狀態。

mysqladmin -h 127.1 -u root -pnew-password ping
mysqladmin -h 127.1 -u root -pnew-password status

2. 用戶管理

嚴禁對用戶的 “host” 部分采用 “%”,除非你想從世界任何一個地方登陸;默認不要使用 GRANT ALL ON . 給用戶過度賦權,

mysql> CREATE USER ‘user‘ IDENTIFIED BY ‘password‘;
mysql> GRANT privileges TO ‘user‘@‘host‘ [WITH GRANT OPTION];
mysql> FLUSH PRIVILEGS;

mysql> GRANT privileges  TO ‘user‘@‘host‘ IDENTIFIED BY ‘password‘ [WITH GRANT OPTION];
mysql> FLUSH PRIVILEGS;

3. 連接數是否正常

主要查看客戶是否有由於沒正確關閉連接而死掉的連接,有多少失敗的連接,是否有惡意連接等。

----- 查看連接數,root會看到所有,其它用戶只能看到自己的連接
mysql> SHOW FULL PROCESSLIST;
$ mysqladmin -h host -u user -p processlist

----- 當前失敗連接數
mysql> SHOW GLOBAL STATUS LIKE ‘aborted_connects‘;

----- 由於客戶沒有正確關閉連接而死掉的連接數
mysql> SHOW GLOBAL STATUS LIKE ‘aborted_clients‘;

----- 最大連接數
mysql> SHOW CLOBAL VARIABLES LIKE ‘max_connections‘;
mysql> SHOW GLOBAL STATUS LIKE ‘max_connections‘;

4. 慢查詢日誌

慢查詢日誌對 SQL 調優來說是非常重要的,它記錄了超過指定時間 long_query_time 的查詢語句;一般只在需要時開啟。

MyISAM

在對 MyISAM 存儲引擎調優時,很多文章推薦使用 Key_read_requests 和 Key_reads 的比例作為調優的參考,來設置 key_buffer_size 參數的值,而實際上這是錯誤的,詳細可以參考 Why you should ignore MySQL’s key cache hit ratio 這篇文章。

簡單介紹如下。

rate VS. ratio

首先需要註意的是,這裏有兩個重要的概念:”miss rate” 一般是每秒 miss 的數目;”miss ratio” 表示從磁盤讀取和從 cache 讀取的比例,該參數沒有單位。

如下的兩個參數可以通過 SHOW GLOBAL STATUS 命令查看,官方文檔的解釋如下。

Key_read_requests
The number of requests to read a key block from the cache.

Key_reads
The number of physical reads of a key block from disk.

也就是說,兩者分別對應了:A) 從緩存讀取索引的請求次數;B) 從磁盤讀取索引的請求次數。

NOTE: 實際上,Key_reads 統計的並非嚴格意義上的讀磁盤,嚴格來說應該是發送系統請求的次數。如果文件系統中有緩存的話,實際耗時就是系統調用,並沒有磁盤讀取的耗時。

很多人認為 Key_reads/Key_read_requests 越小越好,否則就應該增大 key_buffer_size 的設置,但通過計數器的比例來調優有兩個問題:

  1. 比例並不顯示數量的絕對值大小,並不知道總共的請求有多少;
  2. 計數器並沒有考慮時間因素。

假設有兩臺機器,其 miss ratio 分別為 23% 和 0.1% ,因為沒有讀的請求量,很難判斷那臺機器需要進行調優。比如,前者是 23/100,後者則是 10K/10M 。

參數指標

雖說 Key_read_requests 大比小好,但是對於系統調優而言,更有意義的應該是單位時間內的 Key_reads,通常可以通過 Key_reads / Uptime 計算;該參數可以通過如下命令得到:

$ mysqladmin ext -ri10 | grep Key_reads

其中第一行表示的是系統啟動後的總請求,在此可以忽略,下面的每行數值都表示 10 秒內的數據變化,這樣就可以大致評估每秒有多少的磁盤請求,而且可以根據你的磁盤性能進行評估是否合理。

NOTE: 命令裏的 mysqladmin ext 其實就是 mysqladmin extended-status,你甚至可以簡寫成 mysqladmin e 。

結論

通過 Key_reads / Uptime 替換 Key_reads / Key_read_requests 。

xtools

----- 標準數據統計,主要是命令次數的統計,transaction
    ins  Com_insert                               (diff)
    upd  Com_update                               (diff)
    del  Com_delete                               (diff)
    sel  Com_select                               (diff)
    tps  Com_insert + Com_update + Com_delete     (diff)

----- 線程處理,threads
    run  Threads_running
    con  Threads_connected
    cre  Threads_created                          (diff)
    cac  Threads_cached

----- 網絡字節數,bytes
   recv  Bytes_received                           (diff)
   sent  Bytes_sent                               (diff)

----- buffer pool的緩存命中率
         Innodb_buffer_pool_read_requests         邏輯讀總次數
         Innodb_buffer_pool_reads                 物理讀總次數
   read  Innodb_buffer_pool_read_requests         每秒讀請求(diff)
   hits  (Innodb_buffer_pool_read_requests-Innodb_buffer_pool_reads)/Innodb_buffer_pool_read_requests

----- buffer pool頁的狀態,innodb bp pages status
   data  Innodb_buffer_pool_pages_data            已經使用緩存頁數
   free  Innodb_buffer_pool_pages_free            空閑緩存頁數
  dirty  Innodb_buffer_pool_pages_dirty           臟頁數目
  flush  Innodb_buffer_pool_pages_flushed         每秒刷新頁數(diff)

----- innoDB相關的操作,innodb rows status
    ins  Innodb_rows_inserted                     (diff)
    upd  Innodb_rows_updated                      (diff)
    del  Innodb_rows_deleted                      (diff)
   read  Innodb_rows_read                         (diff)

----- 數據讀寫請求數,innodb data status
  reads  Innodb_data_reads                        數據讀總次數(diff)
 writes  Innodb_data_writes                       數據寫的總次數(diff)
   read  Innodb_data_read                         至此已經讀的數據量(diff)
written  Innodb_data_written                      至此已經寫的數據量(diff)

----- 日誌寫入磁盤請求,innodb log
 fsyncs  Innodb_os_log_fsyncs                     向日誌文件寫的總次數(diff)
written  Innodb_os_log_written                    寫入日誌文件的字節數(diff)

參考

可以參考官方文檔 Reference Manual - Server Status Variables,主要介紹各個監控項的含義。

Monitoring MySQL performance metrics,一篇很不錯的介紹 MySQL 監控項文章,包括上述的吞吐量、執行性能、鏈接情況、緩沖池使用情況等。

Why you should ignore MySQL’s key cache hit ratio 這篇文章介紹了 MyISAM 緩存的調優,其中的思想其它參數也可以考慮,也可以參考 本地文檔 。

原文:https://jin-yang.github.io/post/mysql-monitor.html

MySQL 監控指標