如何排查MySQL因为磁盘IO被打满导致的事务提交变慢问题?

雨芳酱_9505

雨芳酱_9505

2026-07-27

503人浏览

原创

八成是磁盘响应跟不上fsync(3),需用strace盯worker线程、iostat/iotop验证io瓶颈,并结合innodb日志状态与变量确认刷盘滞后。

如何排查mysql因为磁盘io被打满导致的事务提交变慢问题?

strace盯住mysqld线程看是否卡在fsync(3)

事务提交慢,八成不是SQL写得差,而是卡在fsync(3)系统调用上。别猜,直接抓证据:strace -p $(pgrep mysqld | head -1) -e trace=fsync,挑一个状态为Updating或Writing to net的线程盯几秒。如果看到fsync(3)调用后长时间没返回(比如 >50ms),基本坐实是磁盘响应跟不上。

注意:别用strace -f全进程跟踪——开销太大,可能干扰本身;也别只盯主线程,要找正在执行COMMIT的worker线程(ps -eo pid,comm,tid,state,wchan,lwp,pcpu,iowait里找iowait高的LWP)。

iostat和iotop交叉验证IO是否真饱和

iostat -x 1输出里只盯两个数字:%util持续 >80% 且 await >10ms(SSD)或 >50ms(HDD),同时出现就是硬瓶颈。单看rkB/s或wkB/s没意义——MySQL刷redo是密集小IO(4KB–16KB),IOPS比吞吐更关键。

接着用iotop -oP确认是不是mysqld在刷盘:WRITE列占比超60%,且IO>列数值频繁跳动,说明压力确实来自MySQL。云盘场景(如ESSD、gp3)还要加一句:iotop -p $(pgrep mysqld)看实际发出的写请求大小和频率,再查控制台IOPS配额是否耗尽。

  • 机械盘慎用innodb_flush_method=O_DIRECT,可能反而更慢
  • RAID卡缓存失效时,write back会自动降级为write through,日志写变同步阻塞
  • redo日志文件(ib_logfile*)所在磁盘必须单独监控,别和data目录混在一起看

查InnoDB状态和变量确认日志刷盘滞后

SHOW ENGINE INNODB STATUS\G里的LOG段是核心证据:Log sequence number和Log flushed up to差距持续拉大(比如超过200MB),说明log buffer写入速度远超刷盘能力;Last checkpoint at长期不动,也佐证checkpoint被拖住。

MySQL
MySQL

编写正确的MySQL查询,避免字符集、索引和锁方面的常见陷阱。

下载

再查状态变量:Innodb_os_log_pending_fsyncs非零且持续上升,Innodb_log_writes随TPS线性飙升,Innodb_buffer_pool_hit_rate低于99%——最后这个值低,说明热数据根本没留在内存,先优化查询和buffer pool大小,别急着调IO参数。

  • Innodb_log_file_size太小(如默认48M)会导致高频checkpoint,表现为周期性毛刺(每1–2分钟卡一下)
  • 调整它必须停库:SET GLOBAL innodb_fast_shutdown = 0 → 关mysqld → 删除ib_logfile0/ib_logfile1 → 改配置 → 启动
  • innodb_log_files_in_group只影响文件个数,总容量由innodb_log_file_size × innodb_log_files_in_group决定

autocommit关了会制造“假慢”

很多ORM或连接池默认关闭autocommit,结果所有DML堆在一个事务里,最后COMMIT才爆发式刷盘——这不是慢,是压根没提交。连上就查:SELECT @@autocommit;,生产环境必须为1。

如果业务真需要长事务,至少确保innodb_flush_log_at_trx_commit=1搭配sync_binlog=1时,别让单条INSERT配一个COMMIT——批量写+合理分批才是解法。否则调参只是掩耳盗铃。

真正棘手的是双刷盘叠加:innodb_flush_log_at_trx_commit=1 + sync_binlog=1,每次COMMIT触发两次fsync,哪怕换NVMe也照样卡。这时候看证据比拍脑袋调参重要得多。

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

2023.10.12

4203

8

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.27

891

4

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

2024.02.23

1089

5

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

6081

10

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

2963

4

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

2024.04.07

6060

11

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

2024.04.29

8161

6

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

1110

5

sql中删除一列的命令是什么
sql中删除一列的命令是什么

在sql中,使用alter table语句可以删除一列,语法为:alter table table_name drop column column_name。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

972

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL vs MySQL
PostgreSQL vs MySQL

共1课时 | 183人学习