net_read_timeout和net_write_timeout分别控制MySQL服务端从客户端读取数据和向客户端写入数据的超时时间,默认值为30秒和60秒,适用于已建立连接后的数据收发阶段,而非空闲或连接建立阶段;设错会导致大查询中断、mysqldump导出失败或连接假死。

读写超时不是靠 wait_timeout 控制的,而是由 net_read_timeout 和 net_write_timeout 决定;设错会导致大查询中断、导出失败或连接假死,但很多人误调 wait_timeout 白忙一场。
net_read_timeout 和 net_write_timeout 是什么
这两个参数管的是「已建立连接后,数据收发阶段」的等待上限:net_read_timeout 控制 MySQL 等客户端发数据(比如接收大结果集、长事务提交)最多忍多久;net_write_timeout 控制 MySQL 往客户端发数据(比如 SELECT 返回百万行)最多等多久。它们和空闲断连无关,也和建连握手无关。
常见错误现象:
- 执行
SELECT * FROM huge_table时突然报Lost connection to MySQL server during query - 用 mysqldump 导出大表中途断开,日志显示
Got timeout reading communication packets - 应用层没报错,但查询返回空或截断——其实是服务端悄悄断了写连接
默认值(net_read_timeout = 30,net_write_timeout = 60)对 OLTP 小查询够用,但对报表、ETL、导出类场景明显偏短。
怎么设才不容易翻车
设值前先看真实负载:查 SHOW PROCESSLIST; 里有没有长时间 Sending data 或 Reading from net 的线程;再翻慢查询日志,确认是否存在 >30 秒的 SELECT 或批量 INSERT。
- 普通 Web API 场景:保持默认或微调 ——
net_read_timeout = 45,net_write_timeout = 90 - 报表/后台任务:设高些 ——
net_read_timeout = 300(5 分钟),net_write_timeout = 600(10 分钟) - 不要无脑设成 0(禁用超时):MySQL 会一直卡住,线程不释放,最终耗尽连接数
- 修改后只影响新连接:老连接仍按旧值运行,需滚动重启或等自然淘汰
和应用层 socketTimeout 的关系别搞混
应用代码里 JDBC URL 加的 socketTimeout=30000,是驱动层控制「单次 TCP read/write 操作」超时;而 net_read_timeout 是服务端内核级控制「整个数据包接收过程」超时。两者叠加生效,但触发逻辑不同。
- 如果
socketTimeout小于net_read_timeout,应用先报错(如Communications link failure) - 如果
net_read_timeout更小,MySQL 主动断连,应用可能收到EOFException或空结果 - 建议:应用层
socketTimeout设为略小于服务端net_read_timeout,留出缓冲(例如服务端设 300,客户端设 28000)
验证改没生效、有没有被覆盖
改完别只信配置文件,直接连上 MySQL 查当前值:
SHOW VARIABLES LIKE 'net%timeout%';
注意:SET GLOBAL net_read_timeout = 300; 会立即生效,但 MySQL 8.0+ 某些版本要求 SUPER 权限,且部分云厂商(如阿里云 RDS)禁止动态修改,必须走控制台或配置模板。
最容易被忽略的一点:这些超时对存储过程内部的网络操作(比如 SELECT ... INTO OUTFILE 或 FEDERATED 表查询)同样起作用,但不会影响事务本身的锁等待 —— 那是 innodb_lock_wait_timeout 管的。


















