InnoDB是MySQL数据库发展至今一款至关重要的数据库存储引擎,其不仅支持事务特性,并且具有丰富的统计信息,便于数据库管理人员了解最近InnoDB存储引擎的运行状态。
早期版本的InnoDB存储引擎通过在内部新建一张名为innodb_monitor的表进行实现,InnoDB内部检测到该表后,会定时输出InnoDB引擎相关统计信息。而现在的InnoDB存储引擎通过命令show engine innodb status实现对InnoDB存储引擎统计信息的查看,在MySQL客户端执行show engine innodb status\G,获取到的结果可能如下:
=====================================
140708 21:35:01 INNODB MONITOR OUTPUT
=====================================
Per second averages calculated from the last 54 seconds
-----------------
BACKGROUND THREAD
-----------------
srv_master_thread loops: 129 1_second, 128 sleeps, 8 10_second, 76 background, 76 flush
srv_master_thread log flush and writes: 129
----------
SEMAPHORES
----------
OS WAIT ARRAY INFO: reservation count 53606, signal count 55906
Mutex spin waits 525951, rounds 2435436, OS waits 40130
RW-shared spins 36905, rounds 444653, OS waits 9660
RW-excl spins 5298, rounds 156489, OS waits 2307
Spin rounds per wait: 4.63 mutex, 12.05 RW-shared, 29.54 RW-excl
------------
TRANSACTIONS
------------
Trx id counter 19FFF
Purge done for trx's n:o < 13696 undo n:o < 0
History list length 15274
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 19F65, not started
mysql tables in use 1, locked 0
MySQL thread id 52, OS thread handle 0x7f8bfd1b9700, query id 1040279 localhost root
SELECT c FROM sbtest1 WHERE id=199077
………………... any other TRANSACTIONS ……………………..
--------
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)
………………. other three read threads …………….….
I/O thread 6 state: waiting for completed aio requests (write thread)
………………. other three write threads …………….….
Pending normal aio reads: 0 [0, 0, 0, 0] , aio writes: 0 [0, 0, 0, 0] ,
ibuf aio reads: 0, log i/o's: 0, sync i/o's: 0
Pending flushes (fsync) log: 1; buffer pool: 0; flash cache 0
296 OS file reads, 47547 OS file writes, 40960 OS fsyncs
0.00 reads/s, 0 avg bytes/read, 755.62 writes/s, 750.19 fsyncs/s
-------------------------------------
INSERT BUFFER AND ADAPTIVE HASH INDEX
-------------------------------------
Ibuf: size 1, free list len 0, seg size 2, 0 merges
merged operations:
insert 0, delete mark 0, delete 0
discarded operations:
insert 0, delete mark 0, delete 0
Hash table size 21249841, node heap has 294 buffer(s)
17860.30 hash searches/s, 13956.39 non-hash searches/s
---
LOG
---
Log sequence number 184703155
Log flushed up to 184699426
Last checkpoint at 109334220
1 pending log writes, 0 pending chkp writes
40703 log i/o's done, 749.84 log i/o's/second
----------------------
BUFFER POOL AND MEMORY
----------------------
Total memory allocated 10994319360; in additional pool allocated 0
Dictionary memory allocated 43910
Buffer pool size 655359
Free buffers 646841
Database pages 8224
Old database pages 3015
Modified db pages 5270
Pending reads 0
Pending writes: LRU 0, flush list 0, single page 0
Pages made young 1, not young 0
0.00 youngs/s, 0.00 non-youngs/s
Pages read 149, created 8075, written 6557
0.00 reads/s, 38.13 creates/s, 5.52 writes/s
Buffer pool hit rate 1000 / 1000, young-making rate 0 / 1000 not 0 / 1000
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 8224, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]
Async Flush: 0, Sync Flush: 0, LRU List Flush: 0, Flush List Flush: 6557
--------------
ROW OPERATIONS
--------------
0 queries inside InnoDB, 0 queries in queue
61 read views open inside InnoDB
Main thread process no. 30423, id 140238424880896, state: sleeping
Number of rows inserted 451965, updated 103933, deleted 51957, read 21009001
962.26 inserts/s, 1924.65 updates/s, 962.15 deletes/s, 381640.41 reads/s
----------------------------
END OF INNODB MONITOR OUTPUT
============================
二、 统计信息说明
根据上面的显示,可以把InnoDB存储引擎的统计信息分为:
1. 基础信息
2. 后台线程(background thread)
3. 信号量(semaphores)
4. 事务(transactions)
5. I/O
6. insert buffer & adaptive hash
7. log
8. buffer pool & memory
9. row operations
下面结合上节中显示的信息分别对以上分类进行说明。
基础信息
Per second averages calculated from the last 54 seconds
InnoDB内部统计的信息都是一段时间内的平均值,默认情况下为60s一个时间间隔计算,上述显示的54s是执行show engine innodb status命令距上次统计结束为54s,下面显示的信息为54s内的平均值,一般认为,该值在比较大时才有意义,因为当该值比较小时,偶然的波动会造成统计信息变化很大,不能很好地反应InnoDB存储引擎内部实际情况。
background thread
-----------------
BACKGROUND THREAD
-----------------
srv_master_thread loops: 129 1_second, 128 sleeps, 8 10_second, 76 background, 76 flush
srv_master_thread log flush and writes: 129
MySQL内部后台有个线程负责数据的刷盘和undo的清理(不使用独立的purge线程)工作,后台线程是一个死循环,根据InnoDB存储引擎的繁忙程度执行数据刷盘操作,主要操作如下图:
从background thread信息中,可以看出1s的循环有129次,10s的循环有8次,128次sleep和76次进入background模式,进行了76次数据刷盘和129次日志刷盘,整个background thread信息显示,InnoDB内部处于相对空闲状态。
semaphores
----------
SEMAPHORES
----------
OS WAIT ARRAY INFO: reservation count 53606, signal count 55906
Mutex spin waits 525951, rounds 2435436, OS waits 40130
RW-shared spins 36905, rounds 444653, OS waits 9660
RW-excl spins 5298, rounds 156489, OS waits 2307
Spin rounds per wait: 4.63 mutex, 12.05 RW-shared, 29.54 RW-excl
信号量段显示了InnoDB存储引擎内部锁信息,在大并发量请求时,InnoDB不可避免存在资源竞争,这个时候,部分事务需要通过锁等待,等待相关事务释放资源后才能继续执行,上面显示的饿信息就是InnoDB内部锁等待信息。除了上面部分信息外,如果InnoDB存储引擎存在死锁状态,还会在以上信息下面增加相应的的死锁信息。
transactions
------------
TRANSACTIONS
------------
Trx id counter 19FFF
Purge done for trx's n:o < 13696 undo n:o < 0
History list length 15274
事务段信息显示当前InnoDB内部正在执行的事务,因为InnoDB存储引擎支持事务并发执行,所以InnoDB内部同时存在许多事务。
事务id在InnoDB内部是递增的,从当前事务信息看,下一个事务id为0x19FFF,而当前purge到的undo日志号no为13695,当前等待purge操作的事务有15274个,单从这些信息上就可以看出,当前InnoDB内部处于繁忙状态,等待pruge的事务数在不断增加。
上面一部分可以看做是事务的总结信息,而LIST OF TRANSACTIONS FOR EACH SESSION:后面显示的是当前InnoDB内部每个事务的具体状态:
---TRANSACTION 19F65, not started
mysql tables in use 1, locked 0
MySQL thread id 52, OS thread handle 0x7f8bfd1b9700, query id 1040279 localhost root
SELECT c FROM sbtest1 WHERE id=199077
上述显示了当前InnoDB内部1个事务的信息,not started说明该事务处于非活动状态,如果是活动状态则为active,mysql tables in use说明当前事务操作的表数,locked表示表被锁的个数(innodb内部支持行锁,所以一般表锁使用比较少,只有在如alter table等操作是才会锁表),mysql thread id为当前连接分配的id,os thread handle为连接线程的句柄,query id为当前查询的id,后面显示了具体的查询SQL。
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)
………………. other three read threads …………….….
I/O thread 6 state: waiting for completed aio requests (write thread)
………………. other three write threads …………….….
Pending normal aio reads: 0 [0, 0, 0, 0] , aio writes: 0 [0, 0, 0, 0] ,
ibuf aio reads: 0, log i/o's: 0, sync i/o's: 0
Pending flushes (fsync) log: 1; buffer pool: 0; flash cache 0
296 OS file reads, 47547 OS file writes, 40960 OS fsyncs
reads/s, 0 avg bytes/read, 755.62 writes/s, 750.19 fsyncs/s
I/O段显示当前InnoDB引擎内部I/O使用情况,InnoDB内部采用异步I/O的模式进行数据的读写操作,默认情况下有1个insert buffer线程,1个日志线程,4个读数据线程和4个写数据线程。
线程信息后面部分为I/O统计信息,总共进行了296次读取,47547次写入,fsync为40960次,平均读数据为0,写输入为755.62次/s, fsyncs为750.19次/s,从以上信息分析,该InnoDB存储引擎内部事务基本上都是写入事务,I/O基本已经达到性能瓶颈。
insert buffer & adaptive hash
-------------------------------------
INSERT BUFFER AND ADAPTIVE HASH INDEX
-------------------------------------
Ibuf: size 1, free list len 0, seg size 2, 0 merges
merged operations:
insert 0, delete mark 0, delete 0
discarded operations:
insert 0, delete mark 0, delete 0
上面部分显示插入缓冲信息,从MySQL 5.5开始,insert buffer不止统计insert信息还包括delete和update信息,被称之为change buffer(delete mark为update的信息,InnoDB内部update通过把记录的delete flag设置成true实现)。
单从上面的信息来看,change buffer没有涉及到需要合并的insert/update/delete操作,insert buffer功能没能得到利用。
Hash table size 21249841, node heap has 294 buffer(s)
17860.30 hash searches/s, 13956.39 non-hash searches/s
InnoDB内部对已某张页查询达到一定数量后,内部会为该页采用哈希方式建立索引,InnoDB认为,当某张页在一段时间被频繁使用时,那么在后面被用到的概率也将非常高,所以为该页建立哈希索引能加速该页的查找。hash table size显示了内部自适应哈希表的大小,hash search和non-hash search分别显示了InnoDB内部查找时使用自适应哈希和普通索引查找每秒的次数,单从上述信息看来自适应哈希查找占到了55%左右,自适应哈希效果明显。
log
---
LOG
---
Log sequence number 184703155
Log flushed up to 184699426
Last checkpoint at 109334220
1 pending log writes, 0 pending chkp writes
40703 log i/o's done, 749.84 log i/o's/second
InnoDB log信息显示了当前内部重做日志(redo log)的写入情况,InnoDB内部通过LSN来实现redo log和事务的对应,log sequence number说明当前系统内部事务执行LSN为184703155,而log flushed up to表示redo log已经保存到磁盘的LSN为184699426,而last checkpoint at表示最近数据和redo log都保存到磁盘的LSN为109334220。
通过上面的信息可以得知:如果这个时候发生某种意外导致MySQL意外宕机,LSN > 184699426的事务可能会被丢失,而LSN在109334220和184699426中间的事务需要通过redo log恢复。LSN < 109334220的数据,因为已经保存到磁盘了,所以不会因为宕机而丢失。
buffer pool & memory
----------------------
BUFFER POOL AND MEMORY
----------------------
Total memory allocated 10994319360; in additional pool allocated 0
Dictionary memory allocated 43910
Buffer pool size 655359
Free buffers 646841
Database pages 8224
Old database pages 3015
Modified db pages 5270
Pending reads 0
Pending writes: LRU 0, flush list 0, single page 0
Pages made young 1, not young 0
0.00 youngs/s, 0.00 non-youngs/s
Pages read 149, created 8075, written 6557
0.00 reads/s, 38.13 creates/s, 5.52 writes/s
Buffer pool hit rate 1000 / 1000, young-making rate 0 / 1000 not 0 / 1000
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 8224, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]
Async Flush: 0, Sync Flush: 0, LRU List Flush: 0, Flush List Flush: 6557
InnoDB内部采用buffer pool的形式缓存数据,对于InnoDB存储引擎来说,buffer pool越大,内存中缓存的数据也就越多,系统的性能就越好。上述信息显示,InnoDB占用内存大约10G,
buffer的大小大约为655359(单位16K,下同),而空闲大约为646841,被使用的页为8224 + 3015,其中脏页为8224, 3015为非脏页。
从上述信息显示,InnoDB内存过大,数据全部落在内存中。
Buffer pool hit rate 1000 / 1000内存命中率100%,等待flush的页为6557
row operations
--------------
ROW OPERATIONS
--------------
0 queries inside InnoDB, 0 queries in queue
61 read views open inside InnoDB
Main thread process no. 30423, id 140238424880896, state: sleeping
Number of rows inserted 451965, updated 103933, deleted 51957, read 21009001
962.26 inserts/s, 1924.65 updates/s, 962.15 deletes/s, 381640.41 reads/s
row operations显示了InnoDB存储引擎内部记录操作信息,打开了61个read views,后面显示了主线程信息和状态,最后显示了自启动以来,所有的insert/update/delete/read数量和每秒的平均值。