Mysql学习4-InnoDB缓存

InnoDB是基于磁盘存储的,其中的存储记录按照页的方式进行管理,可将其视为基于磁盘的数据系统。由于磁盘读写速度与CPU计算速度之间的鸿沟,InnoDB对数据库的读写操作都要通过缓存来实现。在数据库进行读取操作时,先将从磁盘读取到的数据放到缓存池中,这个过程称为将页“FIX”到缓存池,下一次再读取相同的页时,会先读取缓存中的页,没有命中才读取磁盘。在写操作时,先修改缓存中的页,再以一定的频率刷到磁盘中。

1. 缓存池

Mysql通过innodb_buffer_pool_size设置InnoDB的缓存池大小:

# 查看
show variables like 'innodb_buffer_pool_size';
# 修改
set innodb_buffer_pool_size=1000000;

缓存池中存储的数据有:索引页、数据页、undo页、插入缓存、自适应哈希索引、锁信息、数据字典

image-20210221185340722

为了减少数据库内部的资源竞争,Mysql 1.0 之后的版本允许有多个缓存实例,每个页根据hash值分布到不通的缓存实例中(另一个因素是Mysql 1.0 之后,InnoDB使用了AIO,支持多线程读写)。

# 查看InnoDB的缓存池实例数量
show variables like 'innodb_buffer_pool_instance';

2. 缓存策略

数据库中的缓存池通过LRU算法进行管理,将最频繁使用的页放到LRU列表的头部,最少使用的放在尾部,当缓存池内存不足,不能存放新页时,淘汰尾部的页。

缓存池中的页有默认的16kb(由lru管理)和压缩的1kb、2kb、4kb、8kb(由unzip_lru管理)。

InnoBD对LRU算法做了优化:在LRU列表中加入了midpoint位置,当读取到新页时,将新页存放到midpoint位置。又innodb_old_blocks_pct控制,默认为37,即LRU列表中前37%的为new列表,之后的为old列表。

show variables like 'innodb_old_blocks_pct';

另外,innoDB通过innodb_old_blocks_time来进一步管理LRU列表,新读到的页要在这个时间之内再次被读取才会插入到LRU列表中。

show variables like 'innodb_old_blocks_time';

这样做的好处是一些偶然的读取操作不会将LRU列表中的热点数据移出,尤其是一些大的读取操作,如定时任务进行全表读取。

为unzip_lru列表分配内存和一般的分配内存有所不同(因为页的大小不同,而mysql默认的页为16kb)。比从缓存池中申请一个4kb的页,要进行以下步骤:

  1. 检查4kb的unzip_lru列表是否有可用的空闲页
  2. 若有,直接使用
  3. 若无,检查8kb的unzip_lru列表是否有可用的空闲页
  4. 若有,将页分为2个4kb的页,存放到4kb的unzip_lru列表中
  5. 若无,从LRU列表中申请一个16kb的页,分为1个8kb的页和两个4kb的页,分布存放到相应的unzip_lru列表中

**写入缓存:**执行写如操作后,新插入或被修改的页(脏页)会同时存在LRU列表和Flush列表中,LRU列表用来管理缓存池中页的可用性,Flush列表用来管理将页刷如磁盘,二者互不影响。

查看缓存池状态:(非实时)

mysql> show engine innodb status;
----------------------
BUFFER POOL AND MEMORY
----------------------
Total large memory allocated 137428992
Dictionary memory allocated 449278
Buffer pool size   8191     #缓存池中的页数,占用大小:8191*16KB
Free buffers       7089     #Free列表中的页数
Database pages     1095     #LRU列表中的页数
Old database pages 423      #旧LRU SUBLIST的页数
Modified db pages  0        #脏页
Pending reads      0
Pending writes: LRU 0, flush list 0, single page 0
Pages made young 0, not young 0    #插入LRU列表的新页,尚未插入的页
0.00 youngs/s, 0.00 non-youngs/s   #频率
Pages read 948, created 147, written 320
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
No buffer pool page gets since the last printout  #这里会有缓存命中率,因为我没查库,所以没数据
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 1095, unzip_LRU len: 0   #LRU列表的页数和unzip_LRU列表的页数,前者包含后者
I/O sum[0]:cur[0], unzip sum[0]:cur[0]

3. 重做日志缓存

InnoDB先将undo log放到重做日志缓存,再刷到重做日志文件。重做日志缓存的大小由innodb_log_buffer_size控制,默认为8M。一般不用设置的太大,因为master thread每秒都会将重做日志刷到文件。

show variables like 'innodb_log_buffer_size';

将重做日志刷入到文件的情况:

  1. master thread每秒刷一次
  2. 每次事务提交刷一次
  3. 重做日志缓存池剩余内存不足1/2时刷一次
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值