美文网首页
mysql-buffer

mysql-buffer

作者: 甜甜起司猫_ | 来源:发表于2021-06-29 09:52 被阅读0次

    mysql-buffer

    buffer pool

    操作系统,会有缓冲池(buffer pool)机制,避免每次访问磁盘,以加速数据的访问。

    MySQL作为一个存储系统,同样具有缓冲池(buffer pool)机制,以避免每次查询数据都进行磁盘IO。

    InnoDB的缓冲池缓存

    缓存表数据与索引数据,把磁盘上的数据加载到缓冲池,避免每次访问都进行磁盘IO,起到加速访问的作用。

    利用page cache的预读特性,按页读取,所以InnoDB的缓冲池设计:

    1. 磁盘访问按页读取能够提高性能,所以缓冲池一般也是按页缓存数据;
    2. 预读机制启示了我们,能把一些“可能要访问”的页提前加入缓冲池,避免未来的磁盘IO操作

    InnoDB管理这些缓冲页的算法

    MySQL缓冲池污染

    当某一个SQL语句,要批量扫描大量数据时,可能导致把缓冲池的所有页都替换出去,导致大量热数据被换出,MySQL性能急剧下降,这种情况叫缓冲池污染。(类似读写大文件)

    解决污染问题

    MySQL缓冲池加入了一个“老生代停留时间窗口”的机制。

    使用什么参数控制?

    1. innodb_buffer_pool_size
      配置缓冲池的大小,在内存允许的情况下,DBA往往会建议调大这个参数,越多数据和索引放到内存里,数据库的性能会越好。

    2. 参数:innodb_old_blocks_pct
      老生代占整个LRU链长度的比例,默认是37,即整个LRU中新生代与老生代长度比例是63:37。

    如果把这个参数设为100,就退化为普通LRU了。

    1. 参数:innodb_old_blocks_time
      老生代停留时间窗口,单位是毫秒,默认是1000,即同时满足“被访问”与“在老生代停留时间超过1秒”两个条件,才会被插入到新生代头部。

    总结

    1. 缓冲池(buffer pool)是一种常见的降低磁盘访问的机制;
    2. 缓冲池通常以页(page)为单位缓存数据;
    3. 缓冲池的常见管理算法是LRU,memcache,OS,InnoDB都使用了这种算法;
    4. InnoDB对普通LRU进行了优化:
      • 将缓冲池分为老生代和新生代,入缓冲池的页,优先进入老生代,页被访问,才进入新生代,以解决预读失效的问题
      • 页被访问,且在老生代停留时间超过配置阈值的,才进入新生代,以解决批量数据访问,大量热数据淘汰的问题

    change buffer

    innodb的buffer pool特性:

    1. MySQL数据存储包含内存与磁盘两个部分;
    2. 内存缓冲池(buffer pool)以页为单位,缓存最热的数据页(data page)与索引页(index page);
    3. InnoDB以变种LRU算法管理缓冲池,并能够解决“预读失效”与“缓冲池污染”的问题;

    对于读请求,缓冲池能够减少磁盘IO,提升性能,那写请求呢?

    写场景一:

    假如要修改页号为4的索引页,而这个页正好在缓冲池内。操作如下:

    1. 直接修改缓冲池中的页,一次内存操作;
    2. 写入redo log,一次磁盘顺序写操作;

    这样的效率是最大的。像写日志这种顺序写,每秒几万次没问题。

    而且不会出现一致性问题,因为

    1. 读取,会更新缓冲池的页;
    2. 缓冲池LRU数据淘汰,会将“脏页”刷回磁盘;
    3. 数据库异常奔溃,能够从redo log中恢复数据;

    什么时候缓冲池中的页,会刷到磁盘上呢?

    定期刷磁盘,而不是每次刷磁盘,能够降低磁盘IO,提升MySQL的性能

    批量写,是常见的优化手段。


    写场景二:

    要修改页号为40的索引页,而这个页正好不在缓冲池内。操作如下:

    1. 先把需要为40的索引页,从磁盘加载到缓冲池,一次磁盘随机读操作;
    2. 修改缓冲池中的页,一次内存操作;
    3. 写入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的索引页,而这个页正好不在缓冲池内

    流程优化为:

    1. 在写缓冲中记录这个操作,一次内存操作;
    2. 写入redo log,一次磁盘顺序写操作;

    虽然性能和引入前没区别,但是这个页没有读进读缓存中。

    假设之后有请求查询索引页40的数据:

    1. 载入索引页,缓冲池未命中,这次磁盘IO不可避免;
    2. 从写缓冲读取相关信息;
    3. 恢复索引页,放到缓冲池LRU里;

    40这一页,在真正被读取时,才会被加载到缓冲池中。

    change buffer不适用于唯一索引

    如果索引设置了唯一(unique)属性,在进行修改操作时,InnoDB必须进行唯一性检查。也就是说,索引页即使不在缓冲池,磁盘上的页读取无法避免(否则怎么校验是否唯一?),此时就应该直接把相应的页放入缓冲池再进行修改,而不应该再整写缓冲这个幺蛾子。

    相关文章

      网友评论

          本文标题:mysql-buffer

          本文链接:https://www.haomeiwen.com/subject/vwyfultx.html