最近在看《高性能的 Mysql》一書,下面是關於如何學習統計 Mysql 服務器狀態的學習總結,主要是學習使用 SHOW STATUS,SHOW ENGINE INNODB STATUS,SHOW PROCESSLIST,SHOW PROFILE 四個命令。html
mysql> show status like "aborted%";
+------------------+---------+
| Variable_name | Value |
+------------------+---------+
| Aborted_clients | 1439 |
| Aborted_connects | 5025336 |
+------------------+---------+
2 行於數據集 (0.08 秒)
複製代碼
Aborted Connect 表示嘗試鏈接到 MySQL 服務器失敗的次數,引發這個狀態變量激增的緣由以下:node
Aborted Clients 意味着有客戶端成功創建鏈接,可是因爲某些緣由斷開鏈接或者被終止了,這種狀況通常發生在網絡不穩定的環境中。主要的可能性有:mysql
mysql> show status like '%connections%';
+-----------------------------------+-------+
| Variable_name | Value |
+-----------------------------------+-------+
| Connection_errors_max_connections | 0 |
| Connections | 197 |
| Max_used_connections | 2 |
+-----------------------------------+-------+
複製代碼
這邊順便了解一下關於鏈接信息的系統變量配置:算法
mysql> show variables like '%connect%';
+-----------------------------------------------+-----------------+
| Variable_name | Value |
+-----------------------------------------------+-----------------+
| character_set_connection | utf8 |
| connect_timeout | 10 |
| max_connect_errors | 100 |
| max_connections | 151 |
| max_user_connections | 0 |
+-----------------------------------------------+-----------------+
複製代碼
是指 MySQL 服務實例可以同時接受的的最大併發鏈接數。MySQL 實際上支持最大鏈接數加一的算法,保障當鏈接數用完的時候,超級管理員依然能夠和服務端創建鏈接,進行管理。sql
每一個帳號的最大併發鏈接數。數據庫
當某臺非法主機惡意鏈接 MySQL 服務端,遭到的錯誤達到設置值後,MySQL 會拒絕來自該主機的全部鏈接。但執行 flush hosts 後會清零。緩存
在獲取鏈接階段(authenticate)起做用,獲取 MySQL 鏈接是屢次握手的結果,除了用戶名和密碼的匹配校驗外,還有 IP->HOST->DNS->IP 驗證,任何一步均可能由於網絡問題致使線程阻塞。爲了防止線程浪費在沒必要要的校驗等待上,超過 connect_timeout 的鏈接請求將會被拒絕,默認值 10 秒。bash
mysql> show status like 'Thread%';
+-------------------------+-------+
| Variable_name | Value |
+-------------------------+-------+
| Threads_cached | 29 |
| Threads_connected | 94 |
| Threads_created | 417 |
| Threads_running | 2 |
+-------------------------+-------+
6 行於數據集 (0.02 秒)
複製代碼
mysql> show global status like 'Com%';
+-----------------------------+-------+
| Variable_name | Value |
+-----------------------------+-------+
| Com_change_db | 4444 |
| Com_select | 5117790905 |
| Com_alter_db | 0 |
.....
+-----------------------------+-------+
複製代碼
Com_* 開頭的統計信息主要用於記錄每種類型的 SQL 發起過的次數,例如 Com_delete 和 Com_insert 用於統計 Delete 和 Insert 操做的次數,可是若是一次查詢命中緩存,該數字將不會被記錄。注意的是 show global status like 'Com%' 和 show status like 'Com%' 的區別,後者可能只顯示當前會話的統計值。服務器
mysql> show global status like 'Created_tmp%';
+-------------------------+----------+
| Variable_name | Value |
+-------------------------+----------+
| Created_tmp_disk_tables | 8856206 | 臨時表在磁盤的建立量
| Created_tmp_files | 381 | 臨時文件的建立量
| Created_tmp_tables | 26450958 | 臨時表的總的建立量
+-------------------------+----------+
3 行於數據集 (0.14 秒)
複製代碼
經過變量 query_cache_type 來設置是否開啓緩存,經過變量 query_cache_limit 來設置緩存結果集的上限,若是某次查詢超過該上限制則不進行緩存網絡
mysql> show global status like 'Qcache%';
+-------------------------+----------+
| Variable_name | Value |
+-------------------------+----------+
| Qcache_free_blocks | 1 | 這個表示目前處於空閒狀態的 query cache 中內存 block 的數目
| Qcache_free_memory | 1031832 | 緩存中空閒內存總量
| Qcache_hits | 0 | 緩存命中次數
| Qcache_inserts | 0 | 緩存失效次數
| Qcache_lowmem_prunes | 0 | 緩存出現內存不足而且必需要進行清理以便爲 Qcache_inserts 動做騰出空間的次數
| Qcache_not_cached | 17841427 | 沒有進行緩存的查詢的數量
| Qcache_queries_in_cache | 0 | 當前在 query_cache 中‘註冊’的 select 語句條數
| Qcache_total_blocks | 1 | 緩存中塊的總量
+-------------------------+----------+
8 行於數據集 (0.12 秒)
複製代碼
Select.* 統計特定類型 Select 查詢的計數器,它能夠幫咱們瞭解各類查詢計劃
mysql> show global status like 'Select%';
+------------------------+----------+
| Variable_name | Value |
+------------------------+----------+
| Select_full_join | 7224 |
| Select_full_range_join | 0 |
| Select_range | 72966 |
| Select_range_check | 0 |
| Select_scan | 22053174 |
+------------------------+----------+
5 行於數據集 (0.17 秒)
複製代碼
當 mysql 不能使用一個索引來進行預先排序的時,必須使用文件排序,這就會增長 Sort* 狀態變量的值,
mysql> show global status like "Sort%";
+-------------------+---------+
| Variable_name | Value |
+-------------------+---------+
| Sort_merge_passes | 256 |
| Sort_range | 31603 |
| Sort_rows | 9718897 |
| Sort_scan | 1727948 |
+-------------------+---------+
4 行於數據集 (0.02 秒)
複製代碼
mysql> show global status like "Table_locks%";
+-----------------------+---------+
| Variable_name | Value |
+-----------------------+---------+
| Table_locks_immediate | 4270707 |
| Table_locks_waited | 0 |
+-----------------------+---------+
2 行於數據集 (0.28 秒)
複製代碼
show engine innodb status 輸出了關於 InnoDB 一些平均值的統計信息,對於數據的採樣計算的時間間隔也不老是相同的,裏面提供了大多數你要想要的統計信息。
該命令輸出是一個單獨的字符串,沒有行和列,分爲不少小段,因此加 \G 參看更爲方便,每一段都對應了 InnoDB 存儲引擎不一樣部分的信息,
-- 表示當前輸出結果是對過去某個時間範圍內 InnoDB 存儲引擎的狀態的統計
Per second averages calculated from the last 60 seconds
複製代碼
InnoDB 存儲引擎的核心操做大部分都集中在 Mater Thread 後臺線程中,該狀態顯示了後臺線程狀態信息,Master Thread 的主要工做:
-----------------
BACKGROUND THREAD
-----------------
# srv_active 爲每秒的循環次數,srv_idle 爲每 10 秒的的循環次數,srv_shutdown 爲中止的循環,一般爲 0
# 若是每秒循環次數少,每 10 秒次數多,證實當前負載很低;若是每秒循環次數多,每 10 秒次數少,遠大於10:1,證實當前負載很高
srv_master_thread loops: 2818842 srv_active, 0 srv_shutdown, 411 srv_idle
# 日誌緩衝刷盤次數
srv_master_thread log flush and writes: 2819194
複製代碼
主要包含了兩種數據:事件計數器以及可選的當前等待線程列表。首先了解一下 InnoDB 如何兩步得到鎖過程:
spin wait 的消耗遠小於 os waits,spin wait 利用 cpu 的空閒時間,檢查鎖的狀態,os Wait 從 CPU 內核中換出當前執行線程以供其它線程使用。因此應儘可能減小 os waits,能夠經過 innodb_sync_spin_loops 參數來平衡 spin wait 和 os wait。
----------
SEMAPHORES
----------
OS WAIT ARRAY INFO: reservation count 293642477 # 表示 InnoDB 產生了多少次操做系統的等待
OS WAIT ARRAY INFO: signal count 117881542 # 表示進入 OS WAIT 的線程被喚醒次數
RW-shared spins 0, rounds 318628772, OS waits 205885745 # 共享鎖
RW-excl spins 0, rounds 2120303681, OS waits 66818882 # 排他鎖
RW-sx spins 16623848, rounds 479205501, OS waits 15180111 # 共享排他鎖
Spin rounds per wait: 318628772.00 RW-shared, 2120303681.00 RW-excl, 28.83 RW-sx
複製代碼
該錯誤通常不會出現,除非你服務器上外鍵錯誤,好比違反外鍵約束去更新,刪除數據,或者去修改外鍵的類型致使類型不匹配,都會報這個錯, show engine innodb status 在每次有新錯誤時,該信息都會被重寫
記錄最近一次死鎖信息,只有產生過死鎖纔會有記錄。該信息對於查看究竟是什麼致使死鎖很是有用
經過下面的信息咱們能夠知道死鎖的發生時間,死鎖裏每一個事務的狀態和信息
------------------------
LATEST DETECTED DEADLOCK
------------------------
190425 18:00:13
*** (1) TRANSACTION:
TRANSACTION 231E7C5DF, ACTIVE 0 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 4 lock struct(s), heap size 1248, 3 row lock(s)
MySQL thread id 1346996, OS thread handle 0x7fd968454700, query id 760545285 10.10.x.x app_user updating
DELETE
FROM db_0.table_0
WHERE ORDER_ID IN ( 456787464 , 456787465 )
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 5 page no 6064 n bits 824 index `orderId_index` of table `db_0`.`table_0` trx id 231E7C5DF lock_mode X waiting
Record lock, heap no 180 PHYSICAL RECORD: n_fields 2; compact format; info bits 32
0: len 8; hex 80000015eb6a1041; asc j A;;
1: len 8; hex 800000002018fce2; asc ;;
*** (2) TRANSACTION:
TRANSACTION 231E7C5DD, ACTIVE 0 sec starting index read, thread declared inside InnoDB 1
mysql tables in use 1, locked 1
5 lock struct(s), heap size 1248, 4 row lock(s)
MySQL thread id 1348165, OS thread handle 0x7fd96669f700, query id 760545283 10.10.x.x app_user updating
DELETE
FROM db_0.table_0
WHERE ORDER_ID IN ( 456787464 , 456787465 )
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 5 page no 6064 n bits 824 index `orderId_index` of table `db_0`.`table_0` trx id 231E7C5DD lock_mode X locks rec but not gap
Record lock, heap no 180 PHYSICAL RECORD: n_fields 2; compact format; info bits 32
0: len 8; hex 80000015eb6a1041; asc j A;;
1: len 8; hex 800000002018fce2; asc ;;
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 5 page no 6064 n bits 824 index `orderId_index` of table `db_0`.`table_0` trx id 231E7C5DD lock_mode X waiting
Record lock, heap no 180 PHYSICAL RECORD: n_fields 2; compact format; info bits 32
0: len 8; hex 80000015eb6a1041; asc j A;;
1: len 8; hex 800000002018fce2; asc ;;
*** WE ROLL BACK TRANSACTION (1) # 這個表示那個事務被選中成爲死鎖的犧牲品
複製代碼
包含了 InnoDB 事務(transaction)的統計信息。
------------
TRANSACTIONS
------------
# 當前的事務 ID,這是一個系統變量,每建立一個新事務會加 1
Trx id counter 319435931
# Purge done for trx's 這個表示清除舊的 MVCC 行時所用到的事務 ID,和當前事務 ID 相比較,能夠知道有多少老版本數據未被清理。
# undo n:o 表示正在使用的 undo 日誌編號,若是是 0 的話,代表處於空閒狀態
Purge done for trx's n:o < 319435931 undo n:o < 0 state: running but idle # 這個表示 InnoDB undo 日誌文件頁面的個數,若是事務執行了更新並提交,這個數字會增長,當清理進程移除舊版本數據時,該值會減小 History list length 1631 複製代碼
在 InnoDB 中大量使用了 AIO(Async IO)來處理 IO 請求,IO Thread 主要是負責這些 IO 請求的回調處理,經過調用 fsync() 函數協調內存與磁盤之間的數據。
主要包括如下幾種 IO 線程:
FILE I/O 顯示了輔助線程的狀態以及性能計數器的狀態
--------
FILE I/O
--------
# 各個輔助線程的狀態信息
I/O thread 0 state: waiting for completed aio requests (insert buffer thread)
I/O thread 1 state: waiting for completed aio requests (log thread)
I/O thread 2 state: waiting for completed aio requests (read thread)
I/O thread 3 state: waiting for completed aio requests (read thread)
I/O thread 4 state: waiting for completed aio requests (read thread)
I/O thread 5 state: waiting for completed aio requests (read thread)
I/O thread 6 state: waiting for completed aio requests (write thread)
I/O thread 7 state: waiting for completed aio requests (write thread)
I/O thread 8 state: waiting for completed aio requests (write thread)
I/O thread 9 state: waiting for completed aio requests (write thread)
# 下面三行顯示的是每一個輔助線程被掛起操做的數目,若是這些 I/O 大部分有掛起的操做,那麼負載可能 I/O 受限
Pending normal aio reads: [0, 0, 0, 0] , aio writes: [0, 0, 0, 0] ,
ibuf aio reads:, log i/o's:, sync i/o's:
Pending flushes (fsync) log: 0; buffer pool: 0
# 顯示的是讀,寫,fsync 調用執行的次數
230490715 OS file reads, 200072148 OS file writes, 154690982 OS fsyncs
# 每一個線程每秒的平均值
17.15 reads/s, 16384 avg bytes/read, 23.65 writes/s, 21.08 fsyncs/s
複製代碼
插入緩存主要用於非彙集索引的插入和更新操做,把屢次插入和更新操做放在一個 Insert Buffer 對象裏,再以必定的頻率進合併更新,提升性能。
InnoDB 會監控對錶上各個索引頁的查詢,若是觀察到經過哈希索引能夠帶來性能提高,則自動創建哈希索引,經過參數 innodb_adaptive_hash_index 來禁用或啓動
INSERT BUFFER AND ADAPTIVE HASH INDEX 顯示了插入緩存和自適應哈希索引的使用狀況。
-------------------------------------
INSERT BUFFER AND ADAPTIVE HASH INDEX
-------------------------------------
# Ibuf 表示已經合併頁的數量,free list len 表示空閒列表長度,seg size 表示 Insert Buffer 的大小,merges 表示合併次數,
Ibuf: size 1, free list len 80, seg size 82, 2639224 merges
# 分別查看 Insert Buffer, Delete Buffer, Purge Buffer 的次數
merged operations:
insert 4178472, delete mark 151972, delete 60065
# 不須要合併的次數
discarded operations:
insert 0, delete mark 0, delete 0
# 自適應 hash 索引的大小
Hash table size 276671, node heap has 5 buffer(s)
Hash table size 276671, node heap has 21 buffer(s)
Hash table size 276671, node heap has 56 buffer(s)
Hash table size 276671, node heap has 210 buffer(s)
Hash table size 276671, node heap has 8 buffer(s)
Hash table size 276671, node heap has 111 buffer(s)
Hash table size 276671, node heap has 9 buffer(s)
Hash table size 276671, node heap has 33 buffer(s)
# 經過 hash 索引查詢每秒個數,沒法經過 hash 索引查詢每秒的個數
4798.09 hash searches/s, 600.67 non-hash searches/s
複製代碼
這部份內容顯示的是關於 InnoDB 重作日誌的統計,如下三種狀況重作日誌都會被刷新到磁盤
---
LOG
---
Log sequence number 197081867058 # 當前日誌 LSN 序號
Log flushed up to 197081867058 # 日誌刷新到磁盤的 LSN 序號
Pages flushed up to 196985565734 # 已經刷新到磁盤頁的 LSN 序號
Last checkpoint at 196985468367 # 上一次 Checkpoint 的 LSN 序號
# 統計日誌的總量及每秒日誌的量
0 pending log flushes, 0 pending chkp writes
142876358 log i/o's done, 18.32 log i/o's/second
複製代碼
這部分信息顯示了關於 InnoDB 緩存池及其如何使用內存的統計,爲了提升數據庫的性能,引入緩存池的概念,經過參數 innodb_buffer_pool_size 能夠設置緩存池的大小,參數 innodb_buffer_pool_instances 能夠設置緩存池的實例個數。緩存池主要用於存儲如下內容:索引頁,數據頁,undo 頁,插入緩存(insert buffer),自適應哈希索引(adaptive hash index),鎖信息,數據字典信息等信息。
----------------------
BUFFER POOL AND MEMORY
----------------------
Total large memory allocated 2198863872 # InnoDB 分配的總內存
Dictionary memory allocated 7884277 # InnoDB 數據字典分配的內存數,
Buffer pool size 131064 # innodb_buffer_pool 頁的數量
Free buffers 1024 # LRU 列表中空閒頁的數量
Database pages 129587 # LRU 列表中非空閒頁的數量
Old database pages 47815 # LRU 列表中 old 頁的數量,new 和 old 頁的分界經過參數 innodb_old_blocks_pct 設置
Modified db pages 20916 # 髒頁的數量
Pending reads 0 # 掛起讀的數量
Pending writes: LRU 0, flush list 0, single page 0 # 掛起的寫的數量
Pages made young 125019609, not young 11734595709
6.70 youngs/s, 109.36 non-youngs/s
# read 是指從磁盤讀到緩存池中,written 是從緩存池寫入磁盤,created 是指在緩存池中分配但沒有從數據文件中讀取的頁
Pages read 230491590, created 15808941, written 53911882
17.15 reads/s, 1.20 creates/s, 4.28 writes/s
# 緩存命中率
Buffer pool hit rate 1000 / 1000, young-making rate 0 / 1000 not 4 / 1000
複製代碼
顯示了 row 操做及其餘一些統計信息
--------------
ROW OPERATIONS
--------------
# queries,表示 innodb 內核中有多少個線程,隊列中有多少個線程
0 queries inside InnoDB, 0 queries in queue
# 表示有多少個讀視圖被打開,一個讀視圖包含從事務開始數據庫內容的 MVCC 快照
0 read views open inside InnoDB
# 內核主線程的狀態,大部分狀況下處於"sleeping",主線程主要工做有 making checkpoint, flushing log, flushing buffer poll pages 等
Process ID=51, Main thread ID=140023262725888, state: sleeping
# 表示多少行被插入,更新和刪除,讀取及每秒讀取信息,可用於監控
Number of rows inserted 637410366, updated 210696023, deleted 335066, read 311734809045
60.43 inserts/s, 9.95 updates/s, 0.00 deletes/s, 48640.59 reads/s
複製代碼
顯示了當前鏈接到 MYSQL 的鏈接或者線程的狀態,除了 root 用戶能看到全部正在運行的線程外,其餘用戶都只能看到本身正在運行的線程,看不到其它用戶正在運行的線程。除非單獨爲這個用戶賦予了 PROCESS 權限。show processlist 的結果其實來自於 information_schema.processlist 表,因此咱們經過查詢 information_schema.processlist 表能夠獲取對於排查性能問題有用的信息,好比哪一個客戶端鏈接信息最多,哪些線程執行時間最長等信息。
SHOW PROCESSLIST\G;
*************************** 238. 行 ***************************
Id : 666748
User : youdata
Host : 10.255.0.2:56058
db : youdata
Command : Sleep
Time : 127
ACK_WAIT_TIME: 0
State :
Info :
*************************** 239. 行 ***************************
Id : 666761
User : youdata
Host : 10.255.0.2:60619
db : NULL
Command : Query
Time : 0
ACK_WAIT_TIME: 0
State : starting
Info : starting
239 行於數據集 (0.51 秒)
複製代碼
下面看一下每一個字段的含義:
- Checking table: 正在檢查數據表
- Closing tables:正在將表中修改的數據刷新到磁盤中,同時正在關閉已經用完的表
- Locked:被其它查詢鎖住了
- Sending data:正在處理 Select 查詢的記錄同時把數據發動到客戶端
- Sorting for group:正在爲 group by 操做作排序
- Updating: 正在尋找匹配的記錄來修改他們
....
複製代碼
mysql> show profiles;
+----------+------------+---------------+----------------+---------------------------------------------------------------------------+
| Query_ID | Duration | Logical_reads | Physical_reads | Query |
+----------+------------+---------------+----------------+---------------------------------------------------------------------------+
| 1 | 0.00019325 | 0 | 0 | select @@version_comment limit 1 |
| 2 | 0.00043125 | 0 | 0 | SELECT DATABASE() |
| 3 | 0.00058600 | 0 | 0 | show databases |
| 4 | 0.00060725 | 0 | 0 | show tables |
| 5 | 0.00013125 | 0 | 0 | show global profiles |
| 6 | 0.00014375 | 0 | 0 | show global profiles |
| 7 | 0.00073550 | 0 | 0 | select * from bigviz_user where email like "%hzzhang%" order by nick desc |
| 8 | 0.01025300 | 0 | 0 | select count(*) from new_component |
+----------+------------+---------------+----------------+---------------------------------------------------------------------------+
8 rows in set, 1 warning (0.00 sec)
複製代碼
mysql> show for query 7;
+----------------------+----------+
| Status | Duration |
+----------------------+----------+
| starting | 0.000158 |
| checking permissions | 0.000013 |
| Opening tables | 0.000028 | 打開表
| init | 0.000073 |
| System lock | 0.000018 | 加鎖
| optimizing | 0.000015 |
| statistics | 0.000026 |
| preparing | 0.000017 |
| Sorting result | 0.000010 | 排序
| executing | 0.000005 |
| Sending data | 0.000029 | 發送數據
| Creating sort index | 0.000223 |
| end | 0.000008 |
| query end | 0.000011 |
| closing tables | 0.000039 | 關閉表
| freeing items | 0.000039 |
| cleaning up | 0.000025 |
+----------------------+----------+
17 rows in set, 1 warning (0.00 sec)
複製代碼