首页 > 数据库 >MySQL之磁盘I/O过高排查

MySQL之磁盘I/O过高排查

时间:2024-04-16 11:35:37浏览次数:30  
标签:MySQL 排查 innodb IO SQL 磁盘 日志

导读

有个MySQL服务器的磁盘I/O总有过高报警,怎么回事?

有哪些原因

MySQL服务器最近总是报告磁盘I/O非常高,出现这种问题,一般来说,磁盘I/O很高无非是下面几个原因引起:

磁盘子系统设备性能差,或采用ext2/ext3之类文件系统,或采用cfq之类的io scheduler,所以IOPS提上不去;

SQL效率不高,比如没有索引,或者一次性读取大量数据,所以需要更多的I/O;

可用内存太小,内存中能缓存/缓冲的数据不多,所以需要更多的I/O。

方法论已有,接下来就是动手开始排查了。

怎么排查

先看磁盘I/O设备,是由十几块SSD组成的RAID 10阵列,按理说I/O性能应该不至于太差,看iops和%util的数据也确实如此。
再来看下文件系统、io scheduler的因素,发现采用xfs文件系统,而且io scheduler用的是noop,看来也不是这个原因。而且看了下iostat的数据,发现iops也不算低,说明I/O能力还是可以的。

再来看看当前的processlist,以及slow query log,也没发现当前有特别明显的slow query,所以也不是这个原因了。

现在只剩下内存不足这个因素了,看了下服务器物理内存是64G,用系统命令 free 看了下,发现大部分都在cached,而free的也不多。观察InnoDB相关的配置以及status,看能不能找到端倪。
首先,看下 innodb-buffer-pool-size 分配了多少:

嗯,分配了18G,好像不是太多啊~
再看一下 innodb status:

重点关注下几个wait值,再看下show engine innodb结果:

更为诡异的是,在已经停掉SLAVE IO & SQL线程后,发现redo log还在一直增长...
第一次看

停掉SLAVE线程后过阵子再看

看到这里,有经验的DBA应该基本上能想明白了,主要是因为 innodb buffer pool 太小,导致了下面几个后果:

  • dirty page 和 data page 之间相互“排挤抢占”,所以会出现 Innodb_buffer_pool_wait_free 事件;
  • redo log 也没办法及时刷新到磁盘中,所以在SLAVE线程停掉后,能看到LSN还在持续增长;
  • 同时我们也看到unpurge的列表也积攒到很大(111万),这导致了ibdata1文件涨到了146G之大,不过这个可能也是因为有某些事务长时间未提交。

还有,不知道大家注意到没,Innodb_row_lock_current_waits 的值竟然是 18446744073709551615(想想bigint多大),显然不可能啊。事实上,这种情况已经碰到过几次了,明明当前没有行锁,这个 status 值却不小,查了一下官方bug库,竟然只报告了一例,bug id是#71520。

解决

既然知道原因,问题解决起来也就快了,我们主要做了下面几个调整:

  • 调大innodb-buffer-pool-size,原则上不超过物理内存的70%,所以设置为40G;
  • 调大innodb-purge-thread,原来是1,调整成4;
  • 调大innodb_io_capacity和innodb_io_capacity_max,值分别为2万和2.5万;

调整完后,重启实例(5.7版本前调整innodb-buffer-pool-size 和 innodb-purge-thread 需要重启才生效)。再经观察,发现IOPS下降的很快,不再告警,同时 Innodb_buffer_pool_wait_free 也一直为 0,unpurge列表降到了数千级别。

IO延迟高可能的原因

压力测试过程中,如果因为资源使用瓶颈等问题引发最直接性能问题是业务交易响应时间偏大,TPS逐渐降低等。而问题定位分析通常情况下,最优先排查的是监控服务器资源利用率,例如先用TOP 或者nmon等查看CPU、内存使用情况,然后在排查IO问题,例如网络IO、磁盘IO的问题。 如果是磁盘IO问题,一般问题是SQL语法问题、MYSQL参数配置问题、服务器自身硬件瓶颈导致IOPS吞吐率问题。
今天主要是讲解MYSQL 参数配置不合理导致在高并发下磁盘IO问题,而MYSQL整体监控优化方案后面会整理《如何轻量化MYSQL服务性能监控》文章出来。

1、 打开日志跟踪引起的磁盘IO问题
例如:MySQL的日志包括错误日志(ErrorLog),更新日志(UpdateLog),二进制日志(Binlog),查询日志(QueryLog),慢查询日志(SlowQueryLog)等,正常情况下,在生产系统或者压力测试环境中很少有系统会时时打开查询日志。因为查询日志打开之后会将MySQL中执行的每一条Query都记录到日志中,会该系统带来比较大的IO负担,而带来的实际效益却并不是非常大.

2、 SQL写法问题引起磁盘IO高
例如:曾经在做某一个项目时,在看到数据库磁盘IO使用率偏高,前端查询业务交易loadrunner显示事物响应时间偏长,通过监控工具抓取对应SQL,通过计划分析,发现该SQL 中使用distinct 又多表关联且是大表、然后使用order by,最终显示10笔数据,而在产生中间过程数据进行筛选时,使用的是临时表,并把数据放入临时表中,内存刚好设置不大,于是放到磁盘中导致IO偏高。
备注:MySQL在执行SQL查询时可能会用到临时表,临时表存储,MySQL会先创建内存临时表,但内存临时表超过配置指定的值后,MySQL会将内存临时表导出到磁盘临时表;

3、 MYSQL参数配置问题
MYSQL默认配置性能低下,只能通过并发下尝试调整参数配置来逐步优化数据库性能,2017年底根据公司要求配合帮助某一家银行业务系统做性能测试,因为测试环境硬件资源有限,我跟公司申请了几台过时的笔记本,然后根据生产环境软件版本等配置要求,进行模拟搭建性能测试环境,基础软件包含:MYSQL5.6 、centos7.2、tomcat7、 JDK1.7、redis。使用的是联想L421 笔记本当MYSQL数据库服务器、L440当tomcat应用服务器,压力测试工具loadrunner、并发用户100,压力测试业务场景:用户登录退出、相关票据信息查询、电子汇票交易流程等,在压力测试过程中发现部分交易在50用户并发时,数据库磁盘I0使用率都偏高,特别是写操作一直很高,例如测试登录退出交易,经监控数据库磁盘IO率一直偏高,如下案例分析讲解:

4、 其它原因

  • 一次请求读写的数据量太大,导致磁盘I/O读写值较大,例如一个SQL里要读取或更新几万行数据甚至更多,这种最好是想办法减少一次读写的数据量;
  • SQL查询中没有适当的索引可以用来完成条件过滤、排序(ORDER BY)、分组(GROUP BY)、数据聚合(MIN/MAX/COUNT/AVG等),添加索引或者进行SQL改写吧;
  • 瞬间突发有大量请求,这种一般只要能扛过峰值就好,保险起见还是要适当提高服务器的配置,万一峰值抗不过去就可能发生雪崩效应;
  • 因为某些定时任务引起的负载升高,比如做数据统计分析和备份,这种对CPU、内存、磁盘I/O消耗都很大,最好放在独立的slave服务器上执行;
  • 服务器自身的节能策略发现负载较低时会让CPU降频,当发现负载升高时再自动升频,但通常不是那么及时,结果导致CPU性能不足,抗不过突发的请求;
  • 使用raid卡的时候,通常配备BBU(cache模块的备用电池),早期一般采用锂电池技术,需要定期充放电(DELL服务器90天一次,IBM是30天),我们可以通过监控在下一次充放电的时间前在业务低谷时提前对其进行放电,不过新一代服务器大多采用电容式电池,也就不存在这个问题了。
  • 文件系统采用ext4甚至ext3,而不是xfs,在高I/O压力时,很可能导致%util已经跑到100%了,但iops却无法再提升,换成xfs一般可获得大幅提升;
  • 内核的io scheduler策略采用cfq而非deadline或noop,可以在线直接调整,也可获得大幅提升。

转载至

https://mp.weixin.qq.com/s?__biz=MjM5NzAzMTY4NQ==&mid=2653929453&idx=1&sn=acfdda3bbf165b2f094d0d9f021f0bec&scene=21#wechat_redirect

标签:MySQL,排查,innodb,IO,SQL,磁盘,日志
From: https://www.cnblogs.com/OpenSourceSite/p/18137576

相关文章

  • mysql5.7 dump GTID一致性的问题
    利用mysqldump导出数据时提示warning,ApartialdumpfromaserverthathasGTIDsubt@ubt-All-Series:~$mysqldump-uroot-psdxdb>sdxdb.sqlWarning:ApartialdumpfromaserverthathasGTIDswillbydefaultincludetheGTIDsofalltransactions,eventhoseth......
  • 数据库的基本使用-mysql
    https://blog.csdn.net/weixin_50964512/article/details/1246452121.showdatabases;//显示当前已有的数据库2.createdatabasetest2;//创建新的数据库3.usetest1;//使用test1数据库,接下来的操作基于该数据库4.exit;//退出sql//数据表增删改查select*......
  • 美团二面:如何保证Redis与Mysql双写一致性?连续两个面试问到了!
    引言Redis作为一款高效的内存数据存储系统,凭借其优异的读写性能和丰富的数据结构支持,被广泛应用于缓存层以提升整个系统的响应速度和吞吐量。尤其是在与关系型数据库(如MySQL、PostgreSQL等)结合使用时,通过将热点数据存储在Redis中,可以在很大程度上缓解数据库的压力,提高整体系统的......
  • MySQL千万数据,怎么快速查询?
    前言面试官:来说说,一千万的数据,你是怎么查询的?me:直接分页查询,使用limit分页。面试官:有实操过吗?me:肯定有呀此刻献上一首《凉凉》也许有些人没遇过上千万数据量的表,也不清楚查询上千万数据量的时候会发生什么。今天就来带大家实操一下,这次是基于MySQL5.7.26做测试准备数据......
  • 开机后mysql服务未启动问题解决
    问题:mysql的启动类型设置了自动,但是电脑开机后还是需要手动启动。 解决方法:一、Win+R快捷键弹出运行框 二、输入regedit后回车 三、地址栏内输入计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control后回车 四、找到Control入径后,新建一个名称为ServicesPipe......
  • 【MySQL】二进制安装MySQL
    【MySQL】二进制安装MySQL一、基于Ubuntu二进制安装MySQL8.0(5.7+适用)1、创建用户[root@Node-Ubuntu1804-20:~]#groupaddmysql[root@Node-Ubuntu1804-20:~]#useradd-r-gmysql-s/usr/sbin/nologinmysql2、创建目录[root@Node-Ubuntu1804-20:~]#mkdir/data/mysql......
  • 数据库问题排查以及SQL优化
    数据库CPU飙高通过top等命令确定是否数据库进程CPU飙高通过命令showprocesslist找出耗资源较大的SQL如果没有特别耗资源的SQL,就查看session是不是突然增多,可以通过限制连接数如果有特别耗资源的SQL,排查耗资源的SQL是否命中索引、是否表的数据量特别大kill掉这个消耗大的线程......
  • docker安装mysql8
    一、开始安装#新建挂载目录mkdir-p/opt/docker/mysql/datamkdir-p/opt/docker/mysql/confvim/opt/docker/mysql/conf/my.cnf[root@centos01mysql]#cdconf/[root@centos01conf]#lsmy.cnf[root@centos01conf]#catmy.cnf[client]default-character-set=utf8mb4[m......
  • MySQL 中 DELETE 语句中可以使用别名么?
    1情境deletefromtest1t1wherenotexists(select1fromtest2t2wheret1.id=t2.id);以上sql报错:ERROR1064(42000):YouhaveanerrorinyourSQLsyntax;checkthemanualthatcorrespondstoyourMySQLserverversionfortherightsyntaxtouse......
  • 磁盘IO
    磁盘IO是什么磁盘io,顾名思义就是磁盘的输入输出。即向磁盘写入数据和从磁盘读取数据。I/O读写的类型,大体上讲,I/O的类型可以分为:读/写I/O大/小块I/O连续/随机I/O顺序/并发I/O读/写I/O磁盘是用来给我们存取数据用的,因此当说到IO操作的时候,就会存在两种相对应的操......