MySQL报错ER_IB_ERR_PARALLEL_READ_OOM内存不足问题远程修复思路分享
- 问答
- 2026-01-18 12:07:07
- 3
最近在处理一个线上MySQL数据库的问题时,遇到了一个错误,错误代码是ER_IB_ERR_PARALLEL_READ_OOM,这个错误说白了,就是数据库在执行一种叫做“并行读取”的操作时,电脑的内存不够用了,导致操作失败,这个并行读取功能是InnoDB存储引擎(MySQL最常用的一种数据存储方式)用来加速大表查询的,比如没有索引的全表扫描或者大的范围查询,它会同时用多个线程一起去读数据,想快点干完活,但代价就是需要消耗更多的内存。
当时的情况是,有业务反馈说某个报表查询突然变得特别慢,然后应用日志里就抛出了这个数据库错误,因为数据库服务器在机房,我们只能远程连接上去处理,所以排查过程都是通过命令行完成的。
第一步:确认问题现象

我首先登录到MySQL数据库,查看了数据库的错误日志文件,错误日志的位置可以通过在MySQL里执行 SHOW VARIABLES LIKE 'log_error'; 这个命令找到,打开日志文件后,果然看到了类似这样的报错信息:“InnoDB: Parallel read out of memory”,这证实了确实是ER_IB_ERR_PARALLEL_READ_OOM问题,我注意到在报错的时间点前后,系统的内存使用率有一个尖峰,几乎吃满了所有可用内存。
第二步:理解原因和初步判断
看到报错后,我马上想到了MySQL中控制并行读取的几个关键设置,根据MySQL官方文档的介绍,主要涉及两个参数:

innodb_parallel_read_threads:这个参数控制一次并行查询最多能用多少个线程,默认值通常是4,但可能被人为调高了,线程越多,并行度越高,但需要的内存也越多。innodb_parallel_read_buffer_size:这个参数更重要,它规定了每个并行读取线程可以使用多大的内存作为缓冲区,每个线程都会分配这么大一块内存。
问题就出在这里,总的内存消耗大约是 innodb_parallel_read_threads 乘以 innodb_parallel_read_buffer_size,假如线程数设为8,每个缓冲区大小设为1MB,那么一次并行读取操作可能瞬间就要申请8MB内存,如果同时有多个这样的查询在跑,或者系统本身可用的空闲内存就不多了,就非常容易把内存耗光,触发OOM(内存不足)。
我检查了一下当时的数据配置,发现 innodb_parallel_read_threads 被设置成了16,而 innodb_parallel_read_buffer_size 是默认的128KB,算下来,一个查询最大可能占用 16 * 128KB = 2MB,单看这个值不大,但结合当时系统整体内存已经比较紧张的情况(可能还有其他应用在运行),这个并行查询就成了压垮骆驼的最后一根稻草。
第三步:制定并实施远程修复方案

既然是内存不足,解决办法要么是增加内存(硬件升级),要么是减少内存消耗,硬件升级来不及,所以重点放在调整配置上,我有几个思路:
- 最直接的办法:降低并行度,我选择了调整
innodb_parallel_read_threads这个参数,把它从16临时调低到了4,这样,同样一个查询,最大内存消耗就降到了 4 * 128KB = 512KB,显著减少了压力,在MySQL命令行里,我执行了:SET GLOBAL innodb_parallel_read_threads = 4;这个命令能立刻生效,但重启数据库后会失效,先解决眼前的问题再说。 - 更精细的控制:调整缓冲区大小,如果降低线程数后问题依旧,或者对查询速度下降不满意,可以考虑微调
innodb_parallel_read_buffer_size,但这个东西不是越小越好,缓冲区太小可能会让并行读取的优势丧失殆尽,变得和单线程读差不多慢,所以调整这个参数需要谨慎测试。 - 临时禁用,如果情况非常紧急,可以直接关闭并行读取功能,通过设置
SET GLOBAL innodb_parallel_read_threads = 1;来实现,这样所有的相关查询都会退化成单线程顺序读取,虽然慢,但绝对能避免因它引起的内存问题。 - 治本之策:优化查询和索引,并行读取通常发生在那些无法有效利用索引的大查询上,所以长远来看,最根本的解决办法是检查是哪些SQL语句触发了并行读取,看看能不能通过优化SQL语句、为查询条件添加合适的索引来避免这种全表扫描式的大操作,如果查询能走索引,数据库根本就不会启用并行读取,也就不会有这个内存问题了。
第四步:观察效果和后续行动
在我把 innodb_parallel_read_threads 全局参数调整为4之后,马上让业务方重新跑了一次那个报表查询,这次查询成功完成了,虽然花费的时间比之前内存充足时略长一点,但至少不会报错中断,之后持续观察了一段时间数据库的内存使用情况,没有再出现因并行读取导致的内存尖峰。
我做了两件事:
- 将
innodb_parallel_read_threads=4这个设置写入了MySQL的配置文件(my.cnf),这样即使数据库重启,设置也会保留。 - 给开发团队提了个工单,建议他们分析一下那个报表对应的SQL,检查是否有添加索引优化的空间。
远程解决ER_IB_ERR_PARALLEL_READ_OOM问题的思路就是:通过日志定位问题 -> 理解并行读取的内存消耗原理 -> 优先调整并行线程数这个最有效的参数来快速止血 -> 长期则要优化查询语句本身,整个过程不需要重启数据库,通过SET GLOBAL命令就能在线完成,非常适合远程紧急处理。
本文由酒紫萱于2026-01-18发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:http://www.haoid.cn/wenda/83027.html
