//
Innodb存储引擎的几个小知识点
//
01
innodb_old_blocks_time参数
在Innodb存储引擎中,采用LRU算法来来对热数据进行管理的。关于LRU算法,可以在之前的文章中进行了解:
Innodb对LRU算法进行了改进,从而防止全表扫描等操作,对LRU队列产生影响,这里引入一个参数,innodb_old_blocks_time,该参数用于表示数据页读取到mid位置之后,要等待多久才会加入到LRU队列的热数据端,凭借这个参数,我们可以巧妙的避免大表扫描等操作对热点数据的影响,如下:
set global innodb_old_blocks_time=1000
select * from table...
set global innodb_old_blocks_time=0
如上,先将该参数调成一个比较大的值,是的后续的全表扫描操作的热数据页不会直接转入LRU队列的前端,在执行完毕大查询之后,再将该值改为一个较小的值,从而实现我们想要的效果。
innodb存储引擎本身是多线程模型,因此,后台有多个不同的线程,它们各司其职,互相配合,完成内存池的刷新操作。
02
Checkpoint的分类
今天翻看《MySQL技术内部Innodb存储引擎》一书时,发现书上讲Checkpoint动作分成了下面几类,这里记录下:
其中,sharp checkpoint值得是数据库正常关闭的时候,所有的脏页都需要刷新回磁盘。
fuzzy checkpoint只刷新一部分脏页,而不是所有,这么看来,我们之前理解的checkpoint都指得是fuzzy checkpoint这一类了。
在fuzzy checkpoint中,又分成了4种情况,其中:
master Thread checkpoint是按照一定频率从缓冲池的脏页列表中刷新一定比例的页面到磁盘中,这个过程是异步的,不会对其他操作产生影响;
flush_lru_list checkpoint是因为innodb中始终需要保证LRU列表中有100个左右的空闲数据页可以使用,如果没有,则需要进行checkpoint操作,将LRU列表尾部的数据页移除。
Async/Sync FLush Checkpoint指的是redo log file不可用的情况,需要强制将一些数据页刷新回磁盘,以使得redo log file可以重新循环利用。
Dirty too much,也就是缓冲池中的脏页过多,需要对缓冲池进行刷新到磁盘的处理,一般是在75%的时候出发,当然,我们可以通过参数innodb_max_dirty_pages_pct这个参数来对阈值进行调整。
03
一个MySQL部署错误引出的思考
今天下午在阿里云美国的一个ECS机器上部署MySQL实例,遇到了下面的一个问题:
/usr/local/mysql/bin/mysqld:error while loading shared libraries:libaio.so.1,cannot open shared object file:No such file or directory
当时解决的办法是:
yum -y install libaio
为了弄清楚这个包究竟是干啥的,我查阅了书籍,最后了解到这个库是一个内核级别的异步IO操作库,在编译或者运行MySQL的时候,需要有这个依赖,否则安装部署过程出错。关于它的功能,我举一个例子:
如果我们要访问id=6、7、8的三条记录,假设这三条记录在三个相邻的数据页中,如果使用同步的方法,访问一次,等待结果,那么要进行三次数据页的返回,我们才能得到结果。而一旦启用了异步IO操作,也就是Async IO,那么我们就只需要一次操作,将id=6的数据页取出来,再往后顺延两个数据页,就能够得到id=6、7、8的这三条记录,这样减少了内存和磁盘的交互次数,MySQL的性能也就得到了提升。
除此之外,还查到一个知识点,就是可以通过参数来关闭这个异步IO的功能,如下:
mysql> show variables like "%use_native%";
+-----------------------+-------+
| Variable_name | Value |
+-----------------------+-------+
| innodb_use_native_aio | OFF |
+-----------------------+-------+
1 row in set (0.01 sec)
官方测试,启用该参数,数据恢复速度可以提高75%左右。