时间:2021-07-01 10:21:17 帮助过:2人阅读
由上面一段伪代码可以清楚了解到,innodb1.0x之前,每秒or十秒的io量写死在代码中,由于SSD的出现及磁盘的发展,需要更高的io处理,于是在1.0x版本,引入的innodb_io_capacity参数来动态调节io吞吐量;
innodb_max_dirty_pages_pect 太大(eg: 90%),如果内存太大或者服务器压力过大,则刷新脏页速度会降低,推荐值为75%
1.0x版本,引入了 innodb_adapitive_flushing(自适应刷新)参数,当脏页比例小于innodb_max_dirty_pages_pect时,会进行自动刷新一定数量脏页;(innodb_adapitive_flushing根据产生重做日志redo log的速度决定最适合的刷新脏页数量)
1.0x版本之前,full purge操作,最多回收20个undo页,从1.0x版本,引入了innodb_purge_batch_size参数,可以调控回收undo页数;
show variables like “innodb_purge_batch_size”\G
1.2x版本开始,master thread中刷新脏页操作,分离到单独的page cleaner thread中,减轻master thread负担并进一步提高 系统并发性。
- 插入缓冲(insert buffer) 提高性能
- 两次写(double write) 提高安全性
- 自适应哈希索引(adapitive hash index) innodb内部自动优化
- 异步IO(async IO) 提高并发
- 刷新领接页(flush neighbor page) 提高性能
innodb存储引擎,主键是行唯一的标示符,通常是顺序递增的插入,因此插入聚集索引(primary key)一般是顺序存放的,不需要随机离散读取磁盘,速度很快;
但是通常表不止有聚集索引,还会有一些非聚集索引并且不是顺序存放的,非聚集索引的叶子节点的插入是离散的访问非聚集索引页,随机读取导致了性能下降
对于非聚集索引的插入或更新操作,innodb引入了插入缓冲,
插入或更新非聚集索引时,首先判断对于的非聚集索引页是否在缓冲池中,若果存在,则直接插入;
否则,先放入到inssert buffer对象中,然后再一定的频率或特殊情况下,进行insert buffer 和辅助索引页子节点的merge(合并)操作;(如:master thread 中insert buffer merge);插入缓冲使用条件
- 索引时辅助索引(非聚集索引)
- 索引不是唯一的(unique key 每次插入前都会进行查找是否已经存在)
Innodb1.0x开始引入Change Buffer,将insert buffer根据DML操作(insert,update,delete)不同,分别进行insert buffer, purge buffer,delete buffer;
update 操作:
- 将记录标记为删除
- 真正删除记录
delete buffer 对应将记录标记删除,purge buffer对应将记录真正删除
ps:
当数据库写比较密集时,insert buffer会占用过多缓冲池,默认最大可以占用1/2的缓冲池内存
innodb1.2x开始,可以通过innodb_change_buffer_max_size调节change buffer最大占用缓冲池的百分比
insert buffer的数据结构是一颗B+树,默认存放在共享表空间中(ibdata1)【tips:当然缓冲池中页有对应的insert buffer 缓冲区】;
insert buffer B+的非叶子节点存放的是查询key(search key);
- space : 待插入记录所在表的空间id(innodb存储引擎中,每个表有一个唯一space id)
- marker : 用于兼容老版本的insert buffer,暂忽略
- offset : 表示页所在的偏移量
当辅助索引要插入到辅助索引页中时,若果该辅助索引页不在缓冲池中,则根据上图 规则构造一个search key并插入到 insert buffer B+树中;
插入叶子节点结构如下:
- IBUF_REC_OFFSET_COUNT : 两个字节,用于排序每个记录进入insert buffer的顺序
为了能够保证每次合并插入缓冲时,每个辅助索引页都有足够的空间进行存储,需要一个特殊的页用来标记每个辅助索引页的可用空间,称这个页为 insert buffer bitmap
每个insert buffer bitmap页追踪16384个辅助索引页(256个区,详情后续innodb 数据也结构会进行详细讲解);
merge insert buffer:
- 辅助索引页被读取到缓冲池
当select查询时,将辅助索引页读入缓冲池时,需要检查insert buffer bitmap页,然后确认该辅助索引页是否存有记录于insert buffer B+树中,如果存在,则将insert buffer B+树中记录插入到该辅助索引页中
- insert buffer bitmap页追踪到该辅助索引页已经无可用空间
insert buffer bitmap页用来追踪每个辅助索引页的可用空间 ,保证至少有1/32页的空间可用,否则会强制进行一次合并,将insert buffer B+树中该页的记录插入到该辅助索引页中
- master thread
主线程,每秒 or 每十秒会进行一次 merge insert buffer操作
当innodb存储引擎正在写入某个页到表中,只写了部分数据(16k的页,写入4k)时,发生了宕机,称为部分写失效(partial page write);
由于重做日志是基于偏移量进行记录的(如偏移299,写’insert data’),如果想通过重做日志进行恢复,必须要页的一份副本;
写数据之前,保存一份页的副本,即doublewrite
double write 有两部分组成:
- double write buffer (2MB)
- 物理磁盘上共享表空间连续的128页 (2MB)
当刷新脏页时,先通过memcpy函数将脏页复制到double write buffer,之后分两次,每次将1MB顺序地写入共享表空间的物理磁盘上(由于是顺序写,速度非常快);然后再离散的将脏页刷回到具体对应的页中;
tips : 有些系统文件提供了部分写失效的防范措施(eg:ZFS文件系统) ,可以通过 innodb_doublewrite = OFF 禁用两次写
innodb存储引擎会监控对表上各索引的查询,如果观察到建立哈希索引可以带来速度提升,则建立哈希索引,称为 自适应哈希索引(adapitive hash index AHI);
AHI通过缓冲池中B+树构造的,因此建立数据很快;
由于哈希索引只能进行等值查询,不能进行范围查询,一定程度上有局限性
可以通过观察has searches 与 non hash searches 考虑是否禁用该特性,默认为开启
当前数据库系统,为了提高磁盘操作性能,都采用了异步IO;
可以通过 show variables like “innodb_use_native_aio”\G 查看是否开启;
当刷新一个脏页时,innodb存储引擎会检测该页所在区(extend)的所有页,如果有其他脏页,则一起进行刷新操作;
tips:
- 对应机械硬盘,邻接页刷新可以将多个IO写操作,通过异步io特性,合并为一个io操作,可以显著提高性能
- 对应SSD,由于有较高的IOPS,建议关闭此特性
无
后续会对 innodb存储引擎相关文件进行探索
mysql 默认引擎innodb 初探(二)
标签: