MySQL有时候同样的语句执行特别慢

主要原因:就是此时MySQL在执行flush操作(将数据持久化到磁盘中)。

一个很形象的比喻:掌柜的记忆是内存,临时记账的黑板是redo log,账本是磁盘

flush:就是将redo log中的内容更新到账本上,不一定是等店铺打样了才这么做。或者是将内存中脏页数据持久化到磁盘中,将其变为干净页或者释放其在内存中占有的空间。执行redo log操作和刷脏页不是同一个操作

脏页:指的是存在内存中的数据页,但是还没有持久化到磁盘中(记录在redo log中,还没有记录在bin log中,有可能丢失)。

四种情况下MySQL会进行flush操作:

  1. redo log满了,MySQL会停止所有更新,将redo log中的数据持久化后再接受数据更新操作—整个数据库停止更新(业务不能接受)—— 黑板记满了;

  2. 内存不够用了,将脏页写到磁盘并释放内存中该页的数据。(由于内存中存在干净页和脏页,MySQL是将最久没用过的数据页内存空间释放,所以不一定每次内存满了都刷脏页,可能只是释放干净页内存空间,实际中很普遍的现象)——掌柜的脑袋记不住了;

    ps
    这里评论区有个好问题:如果是内存中取出最久没有被访问过的数据脏页,将其进行持久化,那么对应的是执行redo log中某个随机位置的sql语句来写入磁盘,这就违背了redo log将MySQL原来的随机io优化为顺序io的目的,会造成redo log空间的磁盘空间碎片以及分页与合并操作?

    解答是:在MySQL刷脏页的时候只是从磁盘中取出脏页中的数据到内存中,然后更新磁盘中的数据,再释放内存中的脏页空间,该过程redo log不会改变,当后续MySQL读取redo log的时候,读到已经被刷新过的脏页的记录时会跳过该记录,因此redo log仍然保证了MySQL数据更新的顺序性(呼应了文章开头说的redo log持久化和刷脏页持久化是两个不同的操作);

  3. 当系统运行负担不大的时候,MySQL一有空就会执行flush ——店铺营业中但没有新顾客;

  4. MySQL关闭时——店铺打样后。

MySQL性能调优之刷脏页控制策略:

  • 通过设置innodb_io_capacity参数来使得MySQL尽可能的调用主机的IO能力(避免出现数据库写入能力低,但主机此时IO压力小的情况),主要考虑内存中脏页占据的比例(不超过75%)以及redo log的占用率(计算复杂就不说了);

  • 通过设置innodb_flush_neighbors为0(8.0以后默认为零),这个参数为1的话,在内存中刷脏页的时候,如果该脏页边上也是脏页,则会连带边上的脏页一起删除(所以可能本来只要刷一张脏页,结果连带刷了好几张脏页),固态硬盘时代完全不需要这种机制。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值