真正省流量的做法是在远端数据库直接生成目标表最小数据集,如用mysqldump --where条件过滤、ssh管道压缩传输、SELECT INTO OUTFILE+LOAD DATA,配合SSH保活配置防中断。
用 mysqldump + --where 直接导出单表子集,避免全量传输
远程拉整库备份再本地解压过滤,本质是拿带宽换时间,网络延迟高时尤其拖垮效率。真正省流量的做法,是在远端数据库直接生成目标表的最小数据集。
常见错误是先 scp 下几百 MB 的 backup.sql,再用 sed 或 awk 截取,结果丢包重传一次就卡住半小时。
-
mysqldump -h remote_host -u user -p --no-create-info --skip-extended-insert --where="id BETWEEN 1000 AND 2000" db_name table_name > table_subset.sql—— 条件越具体,返回行越少,传输量直降 - 避免用
--skip-extended-insert以外的格式(如默认的多值 INSERT),否则WHERE过滤后仍可能含无关语句 - 如果表无主键或条件难写,改用
--where="1=0"先测试连接与权限,再逐步放宽条件
用 ssh 压缩管道替代 scp 分步传输
分两步:先 scp 传文件,再 mysql 导入,中间磁盘 I/O 和临时文件会放大丢包影响。丢一个 TCP 包,scp 得重传整个 chunk;而管道流式压缩能实时丢弃坏帧,恢复更快。
典型场景:从 100MB 备份里提一个 2MB 的表,但网络丢包率 >0.5%,scp 经常卡在 98%。
-
ssh user@remote "mysqldump -u dbuser -p'pass' --no-create-info db_name table_name | gzip" | gunzip | mysql -u local_user -p local_db—— 数据不落地,压缩在远端做,解压在本地流式喂给mysql - 务必加
gzip,实测对 SQL 文本压缩比常达 70%–85%,比减少丢包次数更有效 - 别用
zstd或lz4,除非远端明确装了对应二进制;gzip是 SSH 默认环境最稳的选择
绕过 MySQL 协议层丢包:用 SELECT ... INTO OUTFILE + LOAD DATA INFILE
当 mysqldump 频繁因超时中断(比如报错 MySQL server has gone away),本质是长连接被中间设备(防火墙、NAT)静默断开。此时换协议层更轻的方案更可靠。
适用前提:远端 MySQL 开启了 secure_file_priv 且你能写入该目录;本地有对应权限执行 LOAD DATA。
- 远端执行:
SELECT * FROM table_name WHERE condition INTO OUTFILE '/tmp/table_data.csv' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n'; - 本地用
scp -C(启用压缩)拉 CSV 文件,比拉 SQL 小 30%–50% - 导入时用
LOAD DATA INFILE 'local_path.csv' INTO TABLE table_name FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n';—— 比mysql执行 INSERT 快 5–10 倍,且不依赖网络稳定性
网络层调优:ssh 的 TCPKeepAlive 和 ServerAliveInterval 必须设
很多丢包问题根本不是物理链路差,而是 SSH 连接空闲时被运营商或企业网关 kill 掉,导致后续传输直接 hang 死。这不是数据库或应用层能解决的。
现象:命令跑着跑着不动了,ps 显示 ssh 进程还在,但网络已失联。
- 在
~/.ssh/config中为远端主机加配置:Host remote-db HostName xxx.xxx.xxx.xxx User user TCPKeepAlive yes ServerAliveInterval 30 ServerAliveCountMax 3 -
ServerAliveInterval 30表示每 30 秒发一次心跳;ServerAliveCountMax 3表示连续 3 次无响应就断连并报错,而不是无限等待 - 别依赖客户端
net.ipv4.tcp_keepalive_*系统参数——SSH 自己的 keepalive 更精准,且对加密隧道生效
实际操作中,最易被忽略的是 ServerAliveInterval 没配,或者误以为加了 -o ConnectTimeout=10 就够了。后者只管建连,不管连上之后的保活。一旦链路中间有状态防火墙,10 分钟没流量,连接就静默消失。










