跨国迁移mysql必须调高net_read_timeout至300秒,两端统一max_allowed_packet=512m,启用tcp_tw_reuse及调大内核缓冲区,并强制使用内网或专线链路,否则必然失败。

跨国迁移 MySQL 数据,延迟不是“能不能忍”的问题,而是“不处理就必然失败”——Lost connection to MySQL server during query、Packet for query is too large、Seconds_Behind_Master 拉到小时级,都是表象;根子在 TCP 层抖动、服务端超时过短、大包被截断、以及客户端和服务端参数错配。
net_read_timeout 必须调高,不是 wait_timeout
很多人一遇到断连就去改 wait_timeout,但那是空闲连接超时,对跨国迁移中“建连成功后卡在读响应”的场景完全无效。真正起作用的是 net_read_timeout:它控制服务端等待客户端读取响应的最长时间。
- 默认值 30 秒,在东亚→北美链路中,一个 200MB 的 INSERT 块可能因丢包重传卡住 40+ 秒,直接触发断连
- 建议设为
net_read_timeout = 300(5 分钟),配合net_write_timeout = 300 - 客户端必须同步:JDBC 加
socketTimeout=300000,Python 的mysql-connector-python加connection_timeout=300 -
connect_timeout可设为 30,但再大意义不大——建连慢是物理延迟,不是超时能解决的
max_allowed_packet 要两端一致且够大
跨国迁移用 mysqldump 或 mysqlpump 导出时,默认启用 --extended-insert,会把成千上万行拼成一条超长 INSERT。一旦超过服务端 max_allowed_packet,MySQL 不报错,而是静默截断——你看到的 SQL 文件结尾突兀、导入后少几万行,大概率就是它。
- 源库和目标库的
my.cnf都要设max_allowed_packet = 512M(注意单位是M,不是MB) - 如果用
mysql客户端导入,命令行必须加--max_allowed_packet=512M,否则客户端自己先拦掉 - 不建议设为 0(无限),MySQL 8.0+ 已弃用;512M 对百 GB 级迁移足够,再大反而增加内存压力
- 导出时可加
--skip-extended-insert保兼容,但文件体积翻倍、解析更慢,仅作兜底
TCP 层优化比 MySQL 参数更关键
MySQL 自己没有重传逻辑,一次丢包就整个 packet 重发。跨国链路 RTT 波动大(P99 常达 300–500ms),丢包率稍升就会导致“卡 2 秒→突然后续刷屏”现象。这时候调 innodb_buffer_pool_size 没用,得动内核参数。
- 启用
tcp_tw_reuse = 1:避免高并发迁移时端口耗尽(尤其用mydumper -t 16时) - 调大缓冲区:
net.core.rmem_max = 16777216(16M)、net.core.wmem_max = 16777216 - 配好三元组:
net.ipv4.tcp_rmem = 4096 262144 16777216,让系统根据流量自动扩缩 - 禁用 Nagle 对 binlog 同步有效,但对 mysqldump 这类大块写入收益小,可不设
tcp_nodelay
别走公网,内网或专线是硬门槛
这不是优化建议,是前提条件。公网迁移在跨国场景下基本不可行:云厂商 NAT 网关 5 分钟回收空闲连接、运营商路由抖动、GFW 干扰、出向限速……任何一项都足以让 IO_Running = No 或 SQL_Running = No。
- 确认主从部署在同一云厂商同一地域(如 AWS us-east-1),且已打通 VPC 对等连接或使用高速通道
- 从库
CHANGE MASTER TO MASTER_HOST必须填主库内网 IP(如10.0.1.5),不能填域名或 EIP - 安全组只放通内网 IP 互访,禁止任何公网入口指向数据库端口
- 如果真无法内网互通(如混合云),必须用专线或 WireGuard 隧道封装,把跨境链路“变成”稳定内网
真正容易被忽略的点是:所有这些配置,必须在迁移开始前完成,并验证生效(SHOW VARIABLES LIKE 'net_read_timeout');迁移中途改参数,多数情况需要重启 MySQL,反而中断流程。另外,slave_net_timeout 是从库 IO 线程重连间隔,和迁移无关,别误调它。











