MySQL连接超时卡死主因是max_allowed_packet和net_buffer_length过小,或客户端read/write_timeout未配置;需服务端调参、客户端显式设超时、分批插入(500–2000行)并启用rewriteBatchedStatements=true。

MySQL连接超时直接卡死?先调大max_allowed_packet和net_buffer_length
连接在执行大批量INSERT时突然中断,十有八九是MySQL服务端拒绝接收过长的SQL包。默认max_allowed_packet=4MB,一旦拼接的INSERT ... VALUES (...),(...),...超过这个值,服务端直接断连,客户端报错类似Packets larger than max_allowed_packet are not allowed。
必须在服务端(不是客户端)执行以下命令:
SET GLOBAL max_allowed_packet = 100000000; SET GLOBAL net_buffer_length = 100000;
注意:net_buffer_length影响单行最大长度,max_allowed_packet控制整条SQL上限;改完需重启客户端连接才生效;若用云数据库(如阿里云RDS),得进控制台修改参数组,不能直接SET GLOBAL。
PyMySQL/SQLAlchemy插入时频繁超时?重点看read_timeout和write_timeout
Python侧用pymysql或SQLAlchemy连接MySQL,即使服务端参数调大,客户端仍可能因等待响应太久而主动断开。常见错误如OperationalError: (2013, 'Lost connection to MySQL server during query'),本质是Python驱动等不到结果就放弃了。
创建Engine时必须显式传入超时参数:
-
connect_args={"read_timeout": 600, "write_timeout": 600}—— 给读写各留10分钟 -
pool_timeout=9控制从连接池取连接的等待时间,别设太小(否则拿不到连接就直接报错) -
pool_recycle=3600防止连接空闲太久被MySQL服务端wait_timeout踢掉
漏掉write_timeout是高频坑:批量INSERT属于“写操作”,但很多人只配了read_timeout,导致数据发到一半就被中止。
单次INSERT VALUES太多反而更慢?控制每批500–2000行
不是VALUES越多越好。MySQL解析一条超长INSERT的开销会非线性增长,尤其当单条SQL超过1.5MB时,CPU解析时间可能反超IO收益。同时,它还容易撞上max_allowed_packet硬限制,或触发InnoDB的锁升级(如从行锁升为表锁)。
实操建议按数据行数切分,而非按字节数:
- 纯数值/短字符串字段:每批1500–2000行较稳
- 含TEXT、JSON或长VARCHAR字段:压到500–800行
- 用
pd.read_sql读数据后,用df.iloc[i:i+1000]切片再转to_dict('records'),比全量转再切更省内存
别信“越大越快”的直觉——实测从1000行/批降到500行/批,总耗时常只增3%~5%,但稳定性提升一个数量级。
MyBatis批量插入总超时?rewriteBatchedStatements=true是前提
MyBatis的<foreach></foreach>生成多VALUES SQL只是表象,真正起效依赖JDBC驱动是否把这批参数识别为“可合并批处理”。没加rewriteBatchedStatements=true,MySQL驱动仍会把INSERT INTO t VALUES (?),(?)拆成两条独立语句执行,事务、日志、锁全不省。
URL里必须带上这个参数:
jdbc:mysql://host:3306/db?rewriteBatchedStatements=true&useSSL=false
另外两个关键点:
- SqlSession必须用
ExecutorType.BATCH打开,且手动flushStatements()分段提交,不能只靠最后commit() - 避免在循环里反复
mapper.insert(x)却不flush——一级缓存会累积所有对象,内存爆掉前就先超时了
最易忽略的是:这个参数对MariaDB驱动无效,换用MySQL Connector/J才能生效。


















