master thread
主要负责将缓冲池中的数据异步刷新到磁盘
IO thread
负责IO请求回调,目前包含四种write,read,insert buffer,log io thread
代表参数
innodb_read_io_threads
innodb_write_io_threads
purge thread
事务被提交后,回收已经使用并分配的undo页
代笔参数
innodb_purge_threads
内存
缓冲池
提高数据的读取速率,类型有:数据页,索引页,插入缓冲,undo页,自适应哈希索引
代表参数
innodb_buffer_pool_size 缓冲池大小
innodb_buffer_pool_instances 配置多个缓冲池实例,页将hash分配到各个缓冲池,减少竞争
查看缓冲池状态
innodb_old_blocks_pct LRU算法中新访问的页所放的位置,避免非热点数据挤掉热点数据
innodb_old_blocks_time mid位置什么时候被放入热端
以上参数导致缓存页从not yang->yang状态,即数据页从mid位置放到热端
相应查询:
select pool_id,pool_size,free_buffers,database_pages from innodb_buffer_pool_stats\G;查看缓冲池使用状态
select pool_id,hit_rate,pages_made_young,pages_not_made_young from information_schema.innodb_buffer_pool_stats\G;查看缓冲池运行状态
*************************** 1. row ***************************
pool_id: 0
hit_rate: 0
pages_made_young: 0
pages_not_made_young: 0
1 row in set (0.00 sec)
重做日志缓冲
将重做日志信息放入缓冲区,并按一定频率刷新到重做日志文件。触发条件:master thread每一秒刷数据,每次事务提交,重做日志缓冲池小于1/2
代表参数
innodb_log_buffer_size
Checkpoint技术
1.缩短数据库恢复时间
2.缓冲池不够用时,将脏页刷新到磁盘
3.重做日志不可用时,刷新脏页
数据库发生crash时,不需要重做所有的日志,因为checkpoint之前的页都已经刷新回磁盘,数据库只需要对checkpoint重做日志进行恢复,checkpoint是通过lsn来记录版本的
两种checkpoint:
sharp checkpoint
在数据库关闭时将所有脏页都刷新回磁盘
代表参数
innodb_fast_shutdown=1
fuzzy checkpoint: 按一定比率刷脏回盘
1.master thread checkpoint
按每秒或者每几十秒的速度从缓冲池的脏页列表中刷新一定比例的页回磁盘
2.flush_lru_list checkpoint
保证lru列表中的可用页数量,否则刷脏页回磁盘
代表参数
innodb_lru_scan_depth 控制lru的可用页数量
3.async/sync flush checkpoint
重做日志文件不可用,直接将页刷新回磁盘
4.dirty page too much checkpoint
Master Thread
包含多个循环
在主循环中可分为每秒的操作和每十秒的操作
每一秒的操作:
1.日志缓冲刷新到磁盘,即使这个事务还没有提交
2.合并插入缓冲
3.至多刷新100个innodb的缓冲池中的脏页带磁盘
4.如果当前没有用户活动,则切换到backgroud loop
每十秒的操作:
1.刷新100个脏页到磁盘
2.合并至多5个插入缓冲
3.将日志缓冲刷新到磁盘
4.删除无用的undo页
5.刷新100个或者10个脏页到磁盘
在之前的版本中,innodb最大只会刷新100个脏页和合并20个插入缓冲,一旦超过阈值,可能会导致大量的脏页没有刷回磁盘,那么在恢复的时候需要花费大量的时间,在之后的版本有参数
innodb_io_capacity设置IO的吞吐量
按照以下比率分配:
合并插入缓冲区时,合并插入缓冲的数量为该参数的5%
从缓冲区刷新脏页的数量为该参数
其他代表参数:
innodb_max_dirty_pages_pct 设为为认为脏页太多的阈值,超过后按照刷脏页回磁盘
innodb_adaptive_flushing 自适应设置脏页阈值,源代码中显示这个值是通过判断重做日志产生速度来决定最合适的刷新脏页数量
innodb_purge_batch_size 每次full purge回收undo页的数量
InnoDB关键特性
1.插入缓存
2.两次写
3.自适应哈希索引
4.异步IO
5.刷新领接页
insert buffer
对于插入操作,如果包含一个聚集索引那么插入速度会非常快,因为具有一定的顺序并不需要随机读取另一页中的记录。但是如果插入操作中包含非聚集索引那么由于发生了随机读(这是B+数据结构所决定的),因此innodb中设计将要写入的索引页缓存在insert buffer,再以一定频率和情况对insert buffer结合辅助索引的merge插入,大大提升写入速度。
使用insert buffer饿条件:
1.索引是辅助索引
2.索引不是唯一的 防止插入时发生随机读
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
如上seg size表示当前insert buffer大小,free list代表空闲列表长度,size代表已经合并纪录页的数量,inserts代表插入数,merged recs代表合并纪录数,merges代表合并的次数,merged recs:merges代表离散IO逻辑请求降低的数量
代表参数:
innodb_change_buffering 可以看成change buffer是insert buffer的升级,同样采用辅助非聚集索引对,inserts,deletes等操作类似insert buffer的作用
innodb_change_buffer_max_size
两次写(double write)
insert buffer提高了innodb的性能,而double write提高了其可靠性。在数据库宕机时需要写入某个页但是只写了该页的一部分。可能有人想到使用重做日志文件去恢复,但是重做日志文件记录的是对页的物理操作,而页本身已经发生损坏那么对其进行恢复是没有意义的。也就是说在应用到重做日志之前需要一个页的副本,当写入实效发生时,通过该页的副本来还愿该页,再进行重做。doublewrite由两部分组成,一部分是内存中的doublewrite buffer,另一部分是物理磁盘上共享表空间。在刷新缓冲池中脏页时,并不是直接写入磁盘,而是将脏页复制到内存中的doublewrite buffer,然后再由其写入到共享磁盘,最后再写入到数据文件中。
查看doublewrite运行情况:
mysql> show global status like 'innodb_dblwr%'\G;
*************************** 1. row ***************************
Variable_name: Innodb_dblwr_pages_written
Value: 64
*************************** 2. row ***************************
Variable_name: Innodb_dblwr_writes
Value: 1
上面表示doublewrite一共写了的页和实际写入的比例为64:1,实际上小于这个比值说明系统压力没有那么大。操作系统在页写入磁盘的过程中发生崩溃,那么在恢复过程中先从innodb存储引擎的共享表空间中找到该页的副本,再应用重做日志文件进行恢复。一般情况下innodb_dblwr_pages_written和innodb_buffer_pool_pages_flushed相等。
自适应哈希索引(adaptive hash index)
哈希索引是一种非常快的查找方法,时间复杂度为1,而b+树的查找次数取决于其高度。innodb会监控索引页的查询并创建哈希索引来提高速度,innodb会自动根据访问频率和模式自动地为某些热点页简历哈希索引。AHI要求对这个页的连续访问模式必须是一样的。
mysql>show engine innodb status\G
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 276707, node heap has 1 buffer(s)
0.00 hash searches/s, 0.00 non-hash searches/s
通过比较 hash searches:non-hash searches,可以大概俩节哈希索引创建后的使用效率
代表参数
innodb_adaptive_hash_index 是否开启自适应索引
异步IO
为了提高磁盘操作性能。数据库系统都采用异步IO。与异步IO相对应的是Sync IO,即每进行一次IO操作需要等待其结束才能进行接下来的操作。如果进行一次索引扫描,而索引扫描涉及多个页,那么如果Sync IO扫描,那么无疑花费很长时间。使用mysql的native aio会发出多个IO,并在所有IO结束后merge IO,大大提高了IO效率。
代表参数
innodb_use_native_aio
刷新邻接页
flush neighbor page的工作原理是当刷新脏页时,Innodb会检测该页所在区的所有页,如果是脏页,那么一起刷新
代表参数
innodb_flush_neighbors
启动关闭恢复
innodb_fast_shutdown代表着innodb关闭的行为
0表示MySQL关闭时,inndb完成所有的full purge和merge insert buffer,并将所有的脏页刷新回磁盘,有时候需要耗费一定的时间,如果要升级innodb,那么将这个参数需要为0,然后再关闭数据库
1表示不需要完成上述的full purge和merge insert buffer,但是缓冲池中的一些数据脏页还是会刷新会磁盘
2表示不完成full purge和merge insert buffer,表示不将缓冲池中的数据脏页写回磁盘,而是将日志都写入日志文件,不会有任何事物丢失,但是下次启动时会进行恢复操作
代表参数
innodb_fast_shutdown
innodb_force_recovery影响整个innodb存储引擎恢复的状况,参数默认为0,代表发生恢复时,进行所有的恢复操作,如果数据页发生corruption,会把错误写入错误日志中去。innodb_force_recovery还可以设置为6个非0值
1表示忽略检查到的corrupt页
2阻止master thread线程运行
3不进行事务的回滚操作
4不进行插入缓冲的合并操作
5不查看undo log,innodb存储引擎会将未提交的事务视为已经提交
6不进行前滚操作
代表参数
innodb_fast_shutdown
锁
数据库系统使用锁是为了支持对共享资源进行并发访问,提供数据的完整性和一致性。锁有lock和latch的概念,在innodb存储引擎中,latch又可分为mutex(互斥量)和rwlock(读写锁),且锁定的时间必须非常短,如果持续时间长,性能会非常差,其目的用来保证并发线程操作临界资源的正确性。lock的对象是事务用来锁定数据库中的对象,如表,页,行。并在lock对象在事务commit或rollback。
mysql> show engine innodb mutex;
+--------+----------------+------------+
| Type | Name | Status |
+--------+----------------+------------+
| InnoDB | log0log.cc:907 | os_waits=2 |
+--------+----------------+------------+
show engine innodb mutex输出结果说明
count mutex被请求的次数
spin_waits 自旋锁的次数
spin_rounds 自旋内部循环的总次数
os_waits 表示操作系统等待的次数
os_yields 进行os_thread_yield唤醒操作的次数
os_wait_times 操作体统等待的时间
lock信息就显得直观多,通过show engine innodb status查看
InnoDB锁类型
innoDB存储引擎实现如下两种标准的行级锁
共享锁S,允许事务读一行数据
排他锁X,允许事务删除或更新一行数据
对于一个事务一个事务获得行r的共享锁S,那么另一个事务同样也能获得这个共享锁S,因为事务并没有涉及数据的改变。但是事务中因为数据的修改一旦获得排他锁X,那么其他事务必须等待事务完成才能获取锁。另外关于锁的粒度,如果粗粒度锁导致无法及时获取细粒度锁,那么获取细粒度锁操作会在粗粒度锁的等级添加意向锁,揭示下一次锁请求的类型。意向锁的类型
意外共享锁(IS Lock),事务想要获得一张表中某几行的共享锁
意外排他锁(IX Lock),事务想要获得一张表中某几行的排他锁
show engine innodb status命令来查看锁请求的信息
例如:select * from t where a<4 lock in share mode在等待,RECORD LOCKS space id 30 page no 3 n bit 72 index 'Primary' of table 'test'.'t' trx id 48B89BD lock_mode X lock rec but not gap,这里一看看到锁住的资源。locks rec but not gap代表锁住的是一个索引,不是一个范围。
purge thread
事务被提交后,回收已经使用并分配的undo页
代笔参数
innodb_purge_threads
内存
缓冲池
提高数据的读取速率,类型有:数据页,索引页,插入缓冲,undo页,自适应哈希索引
代表参数
innodb_buffer_pool_size 缓冲池大小
innodb_buffer_pool_instances 配置多个缓冲池实例,页将hash分配到各个缓冲池,减少竞争
查看缓冲池状态
innodb_old_blocks_pct LRU算法中新访问的页所放的位置,避免非热点数据挤掉热点数据
innodb_old_blocks_time mid位置什么时候被放入热端
以上参数导致缓存页从not yang->yang状态,即数据页从mid位置放到热端
相应查询:
select pool_id,pool_size,free_buffers,database_pages from innodb_buffer_pool_stats\G;查看缓冲池使用状态
select pool_id,hit_rate,pages_made_young,pages_not_made_young from information_schema.innodb_buffer_pool_stats\G;查看缓冲池运行状态
*************************** 1. row ***************************
pool_id: 0
hit_rate: 0
pages_made_young: 0
pages_not_made_young: 0
1 row in set (0.00 sec)
重做日志缓冲
将重做日志信息放入缓冲区,并按一定频率刷新到重做日志文件。触发条件:master thread每一秒刷数据,每次事务提交,重做日志缓冲池小于1/2
代表参数
innodb_log_buffer_size
Checkpoint技术
1.缩短数据库恢复时间
2.缓冲池不够用时,将脏页刷新到磁盘
3.重做日志不可用时,刷新脏页
数据库发生crash时,不需要重做所有的日志,因为checkpoint之前的页都已经刷新回磁盘,数据库只需要对checkpoint重做日志进行恢复,checkpoint是通过lsn来记录版本的
两种checkpoint:
sharp checkpoint
在数据库关闭时将所有脏页都刷新回磁盘
代表参数
innodb_fast_shutdown=1
fuzzy checkpoint: 按一定比率刷脏回盘
1.master thread checkpoint
按每秒或者每几十秒的速度从缓冲池的脏页列表中刷新一定比例的页回磁盘
2.flush_lru_list checkpoint
保证lru列表中的可用页数量,否则刷脏页回磁盘
代表参数
innodb_lru_scan_depth 控制lru的可用页数量
3.async/sync flush checkpoint
重做日志文件不可用,直接将页刷新回磁盘
4.dirty page too much checkpoint
Master Thread
包含多个循环
在主循环中可分为每秒的操作和每十秒的操作
每一秒的操作:
1.日志缓冲刷新到磁盘,即使这个事务还没有提交
2.合并插入缓冲
3.至多刷新100个innodb的缓冲池中的脏页带磁盘
4.如果当前没有用户活动,则切换到backgroud loop
每十秒的操作:
1.刷新100个脏页到磁盘
2.合并至多5个插入缓冲
3.将日志缓冲刷新到磁盘
4.删除无用的undo页
5.刷新100个或者10个脏页到磁盘
在之前的版本中,innodb最大只会刷新100个脏页和合并20个插入缓冲,一旦超过阈值,可能会导致大量的脏页没有刷回磁盘,那么在恢复的时候需要花费大量的时间,在之后的版本有参数
innodb_io_capacity设置IO的吞吐量
按照以下比率分配:
合并插入缓冲区时,合并插入缓冲的数量为该参数的5%
从缓冲区刷新脏页的数量为该参数
其他代表参数:
innodb_max_dirty_pages_pct 设为为认为脏页太多的阈值,超过后按照刷脏页回磁盘
innodb_adaptive_flushing 自适应设置脏页阈值,源代码中显示这个值是通过判断重做日志产生速度来决定最合适的刷新脏页数量
innodb_purge_batch_size 每次full purge回收undo页的数量
InnoDB关键特性
1.插入缓存
2.两次写
3.自适应哈希索引
4.异步IO
5.刷新领接页
insert buffer
对于插入操作,如果包含一个聚集索引那么插入速度会非常快,因为具有一定的顺序并不需要随机读取另一页中的记录。但是如果插入操作中包含非聚集索引那么由于发生了随机读(这是B+数据结构所决定的),因此innodb中设计将要写入的索引页缓存在insert buffer,再以一定频率和情况对insert buffer结合辅助索引的merge插入,大大提升写入速度。
使用insert buffer饿条件:
1.索引是辅助索引
2.索引不是唯一的 防止插入时发生随机读
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
如上seg size表示当前insert buffer大小,free list代表空闲列表长度,size代表已经合并纪录页的数量,inserts代表插入数,merged recs代表合并纪录数,merges代表合并的次数,merged recs:merges代表离散IO逻辑请求降低的数量
代表参数:
innodb_change_buffering 可以看成change buffer是insert buffer的升级,同样采用辅助非聚集索引对,inserts,deletes等操作类似insert buffer的作用
innodb_change_buffer_max_size
两次写(double write)
insert buffer提高了innodb的性能,而double write提高了其可靠性。在数据库宕机时需要写入某个页但是只写了该页的一部分。可能有人想到使用重做日志文件去恢复,但是重做日志文件记录的是对页的物理操作,而页本身已经发生损坏那么对其进行恢复是没有意义的。也就是说在应用到重做日志之前需要一个页的副本,当写入实效发生时,通过该页的副本来还愿该页,再进行重做。doublewrite由两部分组成,一部分是内存中的doublewrite buffer,另一部分是物理磁盘上共享表空间。在刷新缓冲池中脏页时,并不是直接写入磁盘,而是将脏页复制到内存中的doublewrite buffer,然后再由其写入到共享磁盘,最后再写入到数据文件中。
查看doublewrite运行情况:
mysql> show global status like 'innodb_dblwr%'\G;
*************************** 1. row ***************************
Variable_name: Innodb_dblwr_pages_written
Value: 64
*************************** 2. row ***************************
Variable_name: Innodb_dblwr_writes
Value: 1
上面表示doublewrite一共写了的页和实际写入的比例为64:1,实际上小于这个比值说明系统压力没有那么大。操作系统在页写入磁盘的过程中发生崩溃,那么在恢复过程中先从innodb存储引擎的共享表空间中找到该页的副本,再应用重做日志文件进行恢复。一般情况下innodb_dblwr_pages_written和innodb_buffer_pool_pages_flushed相等。
自适应哈希索引(adaptive hash index)
哈希索引是一种非常快的查找方法,时间复杂度为1,而b+树的查找次数取决于其高度。innodb会监控索引页的查询并创建哈希索引来提高速度,innodb会自动根据访问频率和模式自动地为某些热点页简历哈希索引。AHI要求对这个页的连续访问模式必须是一样的。
mysql>show engine innodb status\G
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 276707, node heap has 1 buffer(s)
0.00 hash searches/s, 0.00 non-hash searches/s
通过比较 hash searches:non-hash searches,可以大概俩节哈希索引创建后的使用效率
代表参数
innodb_adaptive_hash_index 是否开启自适应索引
异步IO
为了提高磁盘操作性能。数据库系统都采用异步IO。与异步IO相对应的是Sync IO,即每进行一次IO操作需要等待其结束才能进行接下来的操作。如果进行一次索引扫描,而索引扫描涉及多个页,那么如果Sync IO扫描,那么无疑花费很长时间。使用mysql的native aio会发出多个IO,并在所有IO结束后merge IO,大大提高了IO效率。
代表参数
innodb_use_native_aio
刷新邻接页
flush neighbor page的工作原理是当刷新脏页时,Innodb会检测该页所在区的所有页,如果是脏页,那么一起刷新
代表参数
innodb_flush_neighbors
启动关闭恢复
innodb_fast_shutdown代表着innodb关闭的行为
0表示MySQL关闭时,inndb完成所有的full purge和merge insert buffer,并将所有的脏页刷新回磁盘,有时候需要耗费一定的时间,如果要升级innodb,那么将这个参数需要为0,然后再关闭数据库
1表示不需要完成上述的full purge和merge insert buffer,但是缓冲池中的一些数据脏页还是会刷新会磁盘
2表示不完成full purge和merge insert buffer,表示不将缓冲池中的数据脏页写回磁盘,而是将日志都写入日志文件,不会有任何事物丢失,但是下次启动时会进行恢复操作
代表参数
innodb_fast_shutdown
innodb_force_recovery影响整个innodb存储引擎恢复的状况,参数默认为0,代表发生恢复时,进行所有的恢复操作,如果数据页发生corruption,会把错误写入错误日志中去。innodb_force_recovery还可以设置为6个非0值
1表示忽略检查到的corrupt页
2阻止master thread线程运行
3不进行事务的回滚操作
4不进行插入缓冲的合并操作
5不查看undo log,innodb存储引擎会将未提交的事务视为已经提交
6不进行前滚操作
代表参数
innodb_fast_shutdown
锁
数据库系统使用锁是为了支持对共享资源进行并发访问,提供数据的完整性和一致性。锁有lock和latch的概念,在innodb存储引擎中,latch又可分为mutex(互斥量)和rwlock(读写锁),且锁定的时间必须非常短,如果持续时间长,性能会非常差,其目的用来保证并发线程操作临界资源的正确性。lock的对象是事务用来锁定数据库中的对象,如表,页,行。并在lock对象在事务commit或rollback。
mysql> show engine innodb mutex;
+--------+----------------+------------+
| Type | Name | Status |
+--------+----------------+------------+
| InnoDB | log0log.cc:907 | os_waits=2 |
+--------+----------------+------------+
show engine innodb mutex输出结果说明
count mutex被请求的次数
spin_waits 自旋锁的次数
spin_rounds 自旋内部循环的总次数
os_waits 表示操作系统等待的次数
os_yields 进行os_thread_yield唤醒操作的次数
os_wait_times 操作体统等待的时间
lock信息就显得直观多,通过show engine innodb status查看
InnoDB锁类型
innoDB存储引擎实现如下两种标准的行级锁
共享锁S,允许事务读一行数据
排他锁X,允许事务删除或更新一行数据
对于一个事务一个事务获得行r的共享锁S,那么另一个事务同样也能获得这个共享锁S,因为事务并没有涉及数据的改变。但是事务中因为数据的修改一旦获得排他锁X,那么其他事务必须等待事务完成才能获取锁。另外关于锁的粒度,如果粗粒度锁导致无法及时获取细粒度锁,那么获取细粒度锁操作会在粗粒度锁的等级添加意向锁,揭示下一次锁请求的类型。意向锁的类型
意外共享锁(IS Lock),事务想要获得一张表中某几行的共享锁
意外排他锁(IX Lock),事务想要获得一张表中某几行的排他锁
show engine innodb status命令来查看锁请求的信息
例如:select * from t where a<4 lock in share mode在等待,RECORD LOCKS space id 30 page no 3 n bit 72 index 'Primary' of table 'test'.'t' trx id 48B89BD lock_mode X lock rec but not gap,这里一看看到锁住的资源。locks rec but not gap代表锁住的是一个索引,不是一个范围。