12 mysql性能抖动

sql语句为什么变

在介绍WAL机制时,innodb在处理更新语句的时候,只做了写日志这一个磁盘操作,就是redo log,在更新内存写完redo log之后,就返回客户端成功。

当内存数据页和磁盘数据页内容不一致的时候,称这个内存页为脏页,内存数据写入磁盘后,内存和磁盘上的数据页的内容一致,称为干净页

平时执行很快的更新操作,其实就是在写日志和内存,而mysql偶尔”抖”一下的那个瞬间,可能就是在刷脏页(flush)。

触发数据库的flush

--1 innodb的redo log写满了,这时候系统会停止所有更新操作,把checkpoint往前推进,redo log留出空间可以继续写。
--2 系统内存不足,当需要新的内存页,而内存不够用的时候,就要淘汰一些数据页,空出内存给别的数据页使用。如果淘汰的是脏页,就要先将脏页写盘
--3 mysql认为系统”空闲”的时候,也要找时间,只要有机会就刷一点”脏页”
--4 mysql正常关闭的时候,mysql会把所有内存的脏页都flush到磁盘上。

每个数据页有两种状态

--一种是在内存里,内存里有肯定是正确的结果,直接返回。
--另一种是内存里没有数据,就可以肯定数据文件上是正确的结果,读入内存后返回。

第一种”redo log写满了,要flush脏页”,这种情况innodb要尽量避免,如果出现这种情况,整个系统就不能再接受更新了,所有的更新就必须堵住,从监控上看,更新数为0.

第二种”内存不够用了,要先将脏页写到磁盘”,这种情况其实是常态,innodb用缓冲池(buffer pool)管理内存,缓冲池的内存页有三种状态

--1 还没有使用的
--2 使用了并且是干净页
--3 使用了并且是脏页

Innodb是如何区分一个页是脏页还是干净页呢?在每个数据页的头部有LSN,8个字节,每次修改都会变大,对比这个lsn跟checkipoint的lsn,比checkpoint小的一定是干净页。

Innodb的策略是尽量使用内存,因此对于一个长时间运行的库来说,未被使用的页会很少。

当要读入的数据不在内存时就必须要缓冲池中申请一个数据页,这时候只能把最久不使用的数据页从内存中淘汰掉,如果要淘汰的是一个干净页,就直接释放出来复用,如果是脏页就必须将脏页刷到磁盘,变成干净页后才能复用。

但是出现下面的情况会明显影响性能

--1 一个查询要淘汰的脏页个数太多,会导致查询的响应时间明显变长

--2 日志写满,更新全部堵住,写性能为0,对敏感业务来说,是明显不能接受的。

所以,innodb需要有控制脏页比例的结构来避免这样的情况

Innodb刷脏页的控制策略

要正确的告诉innodb主机的io能力,这样innodb才能知道需要全力刷脏页的时候,可以多块,参数innodb_io_capacity,这个值建议设置磁盘的IOPS,磁盘的iops可以通过fio这个工具来测试,下面的语句用来测试磁盘随机读写的命令

fio -filename=$filename -direct=1 -iodepth 1 -thread -rw=randrw -ioengine=psync -bs=16k -size=500M -numjobs=10 -runtime=10 -group_reporting -name=mytest

Innodb的刷盘速度需要参考这两个因素:一个是脏页比例,一个是redo log写盘速度。

参数innodb_max_dirty_pages_pct是脏页比例上限,默认75%,innodbUI根据当前的脏页比例,算出一个范围在0~100直接的数字

Innodb每次写日志有一个序号,当前写入的需要跟checkpoint对应的序号之间的差值,假设为N,innodb会根据这个N算出一个范围在0~100之间的数字,这个N约大,算出的值就越大。

要尽量避免业务端感受到mysql”抖”一下,就要合理的设置innodb_io_capacity的值,并且平时要多关注脏页比例,不要经常接近75%。

脏页比例

mysql> select VARIABLE_VALUE into @a from global_status where VARIABLE_NAME = 'Innodb_buffer_pool_pages_dirty';
select VARIABLE_VALUE into @b from global_status where VARIABLE_NAME = 'Innodb_buffer_pool_pages_total';
select @a/@b;
(system@127.0.0.1:3306) [information_schema]> select @a/@b;
+------------------------+
| @a/@b |
+------------------------+
| 0.00004577729852902281 |
+------------------------+
1 row in set (0.00 sec) (system@127.0.0.1:3306) [information_schema]> show global status like 'Innodb_buffer_pool_pages_dirty';
+--------------------------------+-------+
| Variable_name | Value |
+--------------------------------+-------+
| Innodb_buffer_pool_pages_dirty | 40 |
+--------------------------------+-------+
1 row in set (0.00 sec) (system@127.0.0.1:3306) [information_schema]> show global status like 'Innodb_buffer_pool_pages_total';
+--------------------------------+--------+
| Variable_name | Value |
+--------------------------------+--------+
| Innodb_buffer_pool_pages_total | 393208 |
+--------------------------------+--------+
1 row in set (0.00 sec) (system@127.0.0.1:3306) [information_schema]> show variables like 'innodb_io_capacity';
+--------------------+-------+
| Variable_name | Value |
+--------------------+-------+
| innodb_io_capacity | 400 |
+--------------------+-------+
1 row in set (0.00 sec) (system@127.0.0.1:3306) [information_schema]> show variables like 'innodb_max_dirty_pages_pct';
+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| innodb_max_dirty_pages_pct | 60 |

在看一个策略

一旦一个查询请求需要在执行过程中先flush掉一个脏页时,这个查询就可能比平时慢了,而mysql中的一个机制可能让你的查询会更慢,

在准备刷一个脏页的时候,如果这个数据页旁边的数据刚好是脏页,就会把这个”邻居”也带着一起刷掉;而这个把邻居一起的逻辑还可以继续蔓延,也就是对于每个邻居数据页,如果跟它相邻的数据页也还是脏页的话,也会被放到一起刷

在innodb中,参数innodb_flush_neighbors用来控制这个行为,值为1的时候有上述刷邻的行为,为0的时候表示不找自己邻居,只刷自己。

这个找邻的优化在机械硬盘时代还是很有意义,可以减少很多随机的io,机械硬盘的iops一般只有几百,相同的逻辑操作减少随机io就意味着系统性能的大幅度提升,

而如果使用ssd这类iops较高的设备的话,建议把该参数设置为0,在mysql 8.0,参数innodb_flush_neighbors默认为0.

思考题

一个内存未128GB,innodb_io_capacity设置为20000的大规格实例,正常建议会将redo log设置为4个1GB文件,但是如果在配置的时候不慎将redo log设置成了1个100M的文件,会发生什么情况?又为什么会出现这样的情况呢?

12 mysql性能抖动的更多相关文章

  1. MySQL性能调优与架构设计——第12章 可扩展设计的基本原则

    第12章 可扩展设计的基本原则 前言: 随着信息量的飞速增加,硬件设备的发展已经慢慢的无法跟上应用系统对处理能力的要求了.此时,我们如何来解决系统对性能的要求?只有一个办法,那就是通过改造系统的架构体 ...

  2. MySQL Disk--SSD磁盘性能抖动问题

    ============================================================= SSD性能 空盘性能:SSD出厂时磁盘没有任何数据情况下的性能 稳态性能:当 ...

  3. MySQL性能调优与架构设计——第10章 MySQL数据库Schema设计的性能优化

    第10章 MySQL Server性能优化 前言: 本章主要通过针对MySQL Server(mysqld)相关实现机制的分析,得到一些相应的优化建议.主要涉及MySQL的安装以及相关参数设置的优化, ...

  4. [原] KVM 环境下MySQL性能对比

    KVM 环境下MySQL性能对比 标签(空格分隔): Cloud2.0 [TOC] 测试目的 对比MySQL在物理机和KVM环境下性能情况 压测标准 压测遵循单一变量原则,所有的对比都是只改变一个变量 ...

  5. Mysql性能优化三(分表、增量备份、还原)

    接上篇Mysql性能优化二 对表进行水平划分 如果一个表的记录数太多了,比如上千万条,而且需要经常检索,那么我们就有必要化整为零了.如果我拆成100个表,那么每个表只有10万条记录.当然这需要数据在逻 ...

  6. MYSQL性能优化的最佳20+条经验

    MYSQL性能优化的最佳20+条经验 2009年11月27日 陈皓 评论 148 条评论  131,702 人阅读 今天,数据库的操作越来越成为整个应用的性能瓶颈了,这点对于Web应用尤其明显.关于数 ...

  7. paip.mysql 性能跟iops的以及硬盘缓存的关系

    paip.mysql 性能跟iops的以及硬盘缓存的关系 作者Attilax  艾龙,  EMAIL:1466519819@qq.com  来源:attilax的专栏 地址:http://blog.c ...

  8. 二十种实战调优MySQL性能优化的经验

    二十种实战调优MySQL性能优化的经验 发布时间:2012 年 2 月 15 日 发布者: OurMySQL 来源:web大本营   才被阅读:3,354 次    消灭0评论     本文将为大家介 ...

  9. 数据库相关文章转载(1) MySQL性能优化之参数配置

    1.目的: 通过根据服务器目前状况,修改Mysql的系统参数,达到合理利用服务器现有资源,最大合理的提高MySQL性能. 2.服务器参数: 32G内存.4个CPU,每个CPU 8核. 3.MySQL目 ...

随机推荐

  1. 记录一下Web开发环境搭建 Eclipse-Java EE 篇

    转自https://www.cnblogs.com/yangyxd/articles/5615965.html Web开发环境搭建 Eclipse-Java EE 篇 [原创内容,转载注名出处] 1. ...

  2. 对bloom的理解 及优化

    varying uv放到vs 讲下bloom的细节 上图这种做法 temporally stable box filtering up 的时候 需要filter 上述upscale有两张srv dow ...

  3. .Net界面开发必备!DevExpress Blazor UI全新组件助力界面开发

    行业领先的.NET界面控件DevExpress 正式发布了v19.1版本,DevExpress UI for Blazor/ Razor组件附带7个用户界面组件(包括Data Grid和Pivot G ...

  4. BZOJ 3626 [LNOI2014]LCA 树剖+(离线+线段树 // 在线+主席树)

    BZOJ 4012 [HNOI2015]开店 的弱化版,离线了,而且没有边权(长度). 两种做法 1 树剖+离线+线段树 这道题求的是一个点zzz与[l,r][l,r][l,r]内所有点的lcalca ...

  5. 题解 【HEOI2016】tree树

    题面 解析 其实这题可以考虑离线做法,用并查集解决. 因为仔细想,添加标记并不方便, 但如果用并查集记录下祖先, 再一一删除,就会方便很多. 先把每次操作记录下来, 同时记录下每个点被标记的次数(因为 ...

  6. 【Wince-自定义控件】ImageButton 带图片、文字

    1.看图 可以实现MouseDown改变背景颜色或背景图片. 遗憾是没有实现键盘触发按钮事件. 2.选择继承自Control基类 public class ImageButton : Control ...

  7. [Python]Python3调用java代码

    环境:Ubuntu16.04 桌面版 Ubuntu安装java的详细教程:https://www.cnblogs.com/ttkl/p/11933884.html 安装JPype1 pip3 inst ...

  8. ListView如何获取点击单元格内容

    Point m_MBRpt = listView1.PointToClient(Control.MousePosition);            ListViewItem lstrow = lis ...

  9. linux下ssh免秘钥登录

    1.检查防火墙是否关闭 (1)切换到root用户 (2)查看防火墙状态 service iptables status 这是没有关闭 (3)设置关闭 service iptables stop 2.检 ...

  10. 小程序日期格式(yyyy-MM-dd HH:mm:ss)转(yyyy/MM/dd HH:mm:ss)

    let newDate = (date).replace(/-/g, '/'); var date = new Date(newDate).getTime();