MySQL一次error writing communication packets的排查过程

本文针对MySQL数据库出现连接失败的问题,详细记录了从page_cleaner报错到最终定位为磁盘性能不足的过程。包括参数调整、慢SQL排查、批量更新策略改进及磁盘性能测试等步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一. 问题描述

今天朋友的数据库出现了一些连接失败
image.png

查看MySQL的错误日志,发现有如下报错:

2021-12-16T09:34:13.091556Z 0 [Note] InnoDB: page_cleaner: 1000ms intended loop took 4177ms. The settings might not be optimal. (flushed=493 and evicted=0, during the time.)
2021-12-16T09:31:55.886147Z 16262 [Note] Aborted connection 16262 to db: ''****'' user: '****' host: ''****'' (Got an error writing communication packets)
2021-12-16T09:31:56.111603Z 16255 [Note] Aborted connection 16255 to db: ''****'' user: '****' host: ''****'' (Got an error writing communication packets)
2021-12-16T09:31:56.303709Z 16236 [Note] Aborted connection 16236 to db: ''****'' user: '****' host: ''****'' (Got an error writing communication packets)
2021-12-16T09:31:56.663354Z 16245 [Note] Aborted connection 16245 to db: ''****'' user: '****' host: ''****'' (Got an error writing communication packets)
2021-12-16T09:31:57.022734Z 16240 [Note] Aborted connection 16240 to db: ''****'' user: '****' host: ''****'' (Got an error writing communication packets)
2021-12-16T09:31:57.256939Z 16004 [Note] Aborted connection 16004 to db: ''****'' user: '****' host: ''****'' (Got an error writing communication packets)

二. 解决方案

2.1 排查page_cleaner的报错

因为每次出现写错误的时候,都会出现这个page_cleaner的报错,首先考虑是资源的问题。

但是朋友的数据库服务器 32核 128GB内存 2T的存储,硬件资源绝对足够,而且在报错期间IO使用率也才20%左右。

首先调整参数

show variables  like '%innodb_io_capacity%';
show variables like '%innodb_max_dirty_pages_pct%';
show variables like '%innodb_max_dirty_pages_pct_lwm%';

set global innodb_io_capacity = 100;
set global innodb_max_dirty_pages_pct = 50;
set global innodb_io_capacity_max = 1000;

观察了一段时间,发现问题依旧。

2.2 排查慢SQL

image.png

image.png

上面 慢日志 Time + Query_time 就刚好是错误日志记录错误的时间了。

900w左右数据的大表直接一个update就更新,难怪会导致写入问题。

写了个存储过程,将单表更新改为 根据id列 分批更新
过了2天,继续观察,问题依旧。

2.3 停应用 分批更新大表

上文提到的 900w左右数据的大表直接一个update就更新,而且这个update语句有30多个,相当于一个900w的大表被更新30多次。

写了个存储过程,将单表更新改为 根据id列 1000条数据更新一次。

delimiter //

drop procedure  if exists p_batch_tmp//

create procedure  p_batch_tmp()
begin

  # 定义一个变量,默认为0
  DECLARE l_count INTEGER DEFAULT 0;  

  # 定义一个开始及结束的值
  DECLARE l_beg INTEGER DEFAULT 1;
  DECLARE l_end INTEGER DEFAULT 1000;
  

  -- 获取表的总行数
  select max(data_id)
    into l_count
   from us_data_payday_demo_copy1;
  
  while l_beg <=  l_count  DO
     -- 分批更新数据
     # 去除前后空格     
    update us_data_payday_demo_copy1 
      set First_Name = trim(First_Name)
      where data_id between l_beg and l_end; 
     commit;

     set l_beg = l_beg + 1000;
     set l_end = l_end + 1000;

  end while;

end;
//

delimiter ;

为了避免网络原因中断,这里使用到mysql的事件

create event evt_now_batch
on schedule 
at now() 
do call p_batch_tmp;

居然发现依旧有 page_cleaner的报错:
InnoDB: page_cleaner: 1000ms intended loop took 4177ms. The settings might not be optimal. (flushed=493 and evicted=0, during the time.)

此时没有应用的更新,只有我存储过程单线程更新大表的数据,而且每一个sql都用到主键 data_id列,居然依旧报错。

2.4 测试磁盘性能

sar命令查看:

sar -d 10 3 -p

%util 为 100.00 代表表示磁盘产生的I/O请求太多,I/O系统已经满负荷的在工作,该磁盘可能存在瓶颈。长期下去,势必影响系统的性能,可以通过优化程序或者通过更换更高、更快的磁盘来解决此问题。
image.png

fio测试
测试随机读命令:

fio -filename=/dev/mapper/centos-home -direct=1 -iodepth 1 -thread -rw=randread -ioengine=psync -bs=16k -size=10G -numjobs=10 -runtime=1000 -group_reporting -name=mytest

输出结果:
cc22e0cb6aed8fd53674cefa62eb514.png

对比下我们公司测试服务器的输出:
569bb3f9b0cdc0f18850956c29bfd91.png

iops 差距在100倍以上
最终问题排查到,是磁盘的IO性能不给力,太慢了。
后来得知朋友的公司使用的是一个很老旧的机器,CPU和内存还算给力,磁盘真的慢到不行。

已经知会朋友,让朋友换硬件。

### MySQL 'Got an error reading communication packets' 的解决方案 当遇到 `Got an error reading communication packets` 错时,这通常意味着客户端与MySQL服务器之间的通信存在问题。此错可能由多种因素引起,包括但不限于网络配置不当、超时设置不合理以及数据包大小限制等。 #### 调整参数设置 为了缓解这一问题,可以尝试调整一些关键的MySQL全局变量来优化连接行为: - **max_allowed_packet**: 增加该值可允许更大的查询语句或返回更多的结果集,从而减少因数据量过大而引发的问题。 ```sql SET GLOBAL max_allowed_packet=1073741824; -- 设置为1GB ``` - **net_read_timeout 和 net_write_timeout**: 这两个参数控制着读写操作等待完成的时间长度,默认情况下它们被设定得相对较低。适当延长这些时间可以帮助处理较慢的数据传输过程。 ```sql SET GLOBAL net_read_timeout=300; SET GLOBAL net_write_timeout=300; ``` 上述更改能够有效改善大多数由于短暂性的网络波动所造成的通讯中断现象[^1]。 #### 检查并修复潜在的硬件和软件故障 除了修改数据库内部配置外,还需考虑外部环境的影响。例如,检查物理链路质量、防火墙策略是否阻止必要的端口访问,甚至排查是否存在恶意攻击企图干扰正常服务运行。对于后者,启用SSL加密机制不失为一种增强安全性和稳定性的方法[^2]。 如果以上措施仍无法彻底解决问题,则建议进一步深入调查具体的业务场景特点及其对应的资源消耗模式,以便采取更有针对性的技术手段加以应对[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值