mysql-buffer
buffer pool
操作系统,会有缓冲池(buffer pool)机制,避免每次访问磁盘,以加速数据的访问。
MySQL作为一个存储系统,同样具有缓冲池(buffer pool)机制,以避免每次查询数据都进行磁盘IO。
InnoDB的缓冲池缓存
缓存表数据与索引数据,把磁盘上的数据加载到缓冲池,避免每次访问都进行磁盘IO,起到加速访问的作用。
利用page cache的预读
特性,按页读取,所以InnoDB的缓冲池设计:
- 磁盘访问按页读取能够提高性能,所以缓冲池一般也是按页缓存数据;
- 预读机制启示了我们,能把一些“可能要访问”的页提前加入缓冲池,避免未来的磁盘IO操作
InnoDB管理这些缓冲页的算法
MySQL缓冲池污染
当某一个SQL语句,要批量扫描大量数据时,可能导致把缓冲池的所有页都替换出去,导致大量热数据被换出,MySQL性能急剧下降,这种情况叫缓冲池污染。(类似读写大文件)
解决污染问题
MySQL缓冲池加入了一个“老生代停留时间窗口”的机制。
使用什么参数控制?
-
innodb_buffer_pool_size
配置缓冲池的大小,在内存允许的情况下,DBA往往会建议调大这个参数,越多数据和索引放到内存里,数据库的性能会越好。 -
参数:innodb_old_blocks_pct
老生代占整个LRU链长度的比例,默认是37,即整个LRU中新生代与老生代长度比例是63:37。
如果把这个参数设为100,就退化为普通LRU了。
- 参数:innodb_old_blocks_time
老生代停留时间窗口,单位是毫秒,默认是1000,即同时满足“被访问”与“在老生代停留时间超过1秒”两个条件,才会被插入到新生代头部。
总结
- 缓冲池(buffer pool)是一种常见的降低磁盘访问的机制;
- 缓冲池通常以页(page)为单位缓存数据;
- 缓冲池的常见管理算法是LRU,memcache,OS,InnoDB都使用了这种算法;
- InnoDB对普通LRU进行了优化:
- 将缓冲池分为老生代和新生代,入缓冲池的页,优先进入老生代,页被访问,才进入新生代,以解决预读失效的问题
- 页被访问,且在老生代停留时间超过配置阈值的,才进入新生代,以解决批量数据访问,大量热数据淘汰的问题
change buffer
innodb的buffer pool特性:
- MySQL数据存储包含内存与磁盘两个部分;
- 内存缓冲池(buffer pool)以页为单位,缓存最热的数据页(data page)与索引页(index page);
- InnoDB以变种LRU算法管理缓冲池,并能够解决“预读失效”与“缓冲池污染”的问题;
对于读请求,缓冲池能够减少磁盘IO,提升性能,那写请求呢?
写场景一:
假如要修改页号为4的索引页,而这个页正好在缓冲池内。操作如下:
- 直接修改缓冲池中的页,一次内存操作;
- 写入redo log,一次磁盘顺序写操作;
这样的效率是最大的。像写日志这种顺序写,每秒几万次没问题。
而且不会出现一致性问题,因为
- 读取,会更新缓冲池的页;
- 缓冲池LRU数据淘汰,会将“脏页”刷回磁盘;
- 数据库异常奔溃,能够从redo log中恢复数据;
什么时候缓冲池中的页,会刷到磁盘上呢?
定期刷磁盘,而不是每次刷磁盘,能够降低磁盘IO,提升MySQL的性能
批量写,是常见的优化手段。
写场景二:
要修改页号为40的索引页,而这个页正好不在缓冲池内。操作如下:
- 先把需要为40的索引页,从磁盘加载到缓冲池,一次磁盘随机读操作;
- 修改缓冲池中的页,一次内存操作;
- 写入redo log,一次磁盘顺序写操作;
没有命中缓冲池的时候,至少产生一次磁盘IO,对于写多读少的业务场景,需要引入写缓冲(change buffer)提高数据库写性能,减低磁盘IO。
在MySQL5.5之前,叫插入缓冲(insert buffer),只针对insert做了优化;现在对delete和update也有效,叫做写缓冲(change buffer)。
它是一种应用在非唯一普通索引页(non-unique secondary index page)不在缓冲池中,对页进行了写操作,并不会立刻将磁盘页加载到缓冲池,而仅仅记录缓冲变更(buffer changes),等未来数据被读取时,再将数据合并(merge)恢复到缓冲池中的技术。写缓冲的目的是降低写操作的磁盘IO,提升数据库性能。
引入change buffer后,两种写场景有什么变化
写场景二:
要修改页号为40的索引页,而这个页正好不在缓冲池内
流程优化为:
- 在写缓冲中记录这个操作,一次内存操作;
- 写入redo log,一次磁盘顺序写操作;
虽然性能和引入前没区别,但是这个页没有读进读缓存中。
假设之后有请求查询索引页40的数据:
- 载入索引页,缓冲池未命中,这次磁盘IO不可避免;
- 从写缓冲读取相关信息;
- 恢复索引页,放到缓冲池LRU里;
40这一页,在真正被读取时,才会被加载到缓冲池中。
change buffer不适用于唯一索引
如果索引设置了唯一(unique)属性,在进行修改操作时,InnoDB必须进行唯一性检查。也就是说,索引页即使不在缓冲池,磁盘上的页读取无法避免(否则怎么校验是否唯一?),此时就应该直接把相应的页放入缓冲池再进行修改,而不应该再整写缓冲这个幺蛾子。
网友评论