最近在看《高性能的 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)
复制代码