直接用mysqldump连远程MySQL失败主因是服务仅监听127.0.0.1或防火墙拦截3306端口,正确解法是通过SSH隧道(ssh -L)将远程3306映射至本地端口,再用mysqldump连接该本地端口完成安全备份。

为什么直接用 mysqldump 连远程数据库会失败
因为多数生产环境的 MySQL 服务默认只监听 127.0.0.1,或者防火墙禁止外部 IP 直连 3306 端口。你看到的 ERROR 2003 (HY000): Can't connect to MySQL server,八成不是密码错,而是网络层被拦了。
这时候硬开公网端口或改 bind-address 风险太高,SSH 隧道才是安全又轻量的解法——它不暴露 MySQL,只借 SSH 的加密通道把本地请求“悄悄”转发过去。
- 必须确保目标服务器上已启用 SSH 服务,且你有对应用户的登录权限(密钥或密码)
- MySQL 用户需具备远程访问权限(哪怕只限
127.0.0.1),因为隧道连进去后,SSH 会把请求转给本机的 MySQL - 别用
root@localhost去连,要用root@127.0.0.1——前者走 socket,后者才走 TCP,而隧道只转发 TCP 流量
怎么建一条可用的 SSH 隧道并 dump 数据
核心是用 ssh -L 把远程 MySQL 的 3306 映射到本地某个空闲端口(比如 3307),然后让 mysqldump 连这个本地端口。
命令分两步走,但可以合并为一行(加 -fN 让 SSH 在后台运行):
ssh -fN -L 3307:127.0.0.1:3306 user@remote-server-ip
接着立刻执行 dump(注意指定 -h 127.0.0.1 -P 3307):
mysqldump -h 127.0.0.1 -P 3307 -u dbuser -p dbname > backup.sql
-
-L 3307:127.0.0.1:3306中的中间地址必须写127.0.0.1,不能写localhost,否则在远程机器上解析可能失败 - 如果远程 MySQL 绑定的是
0.0.0.0或具体内网 IP,这里要同步改成对应地址(如10.0.1.5:3306) - 隧道建立后没有回显,用
lsof -i :3307或netstat -an | grep 3307确认本地端口是否监听成功
备份大库时容易卡住或中断的几个关键点
隧道本身不处理数据流控,mysqldump 一卡,整个连接就挂,尤其是跨公网、带宽窄、或表里有超大 BLOB 字段时。
- 加上
--single-transaction(InnoDB 表适用)避免锁表,但不会减少传输体积 - 用
--compress让 MySQL 客户端和服务端之间启用压缩,对慢链路很有效 - 别用
ssh -o ServerAliveInterval=30就完事——得同时加-o TCPKeepAlive=yes,否则 NAT 设备可能静默断连 - 如果中途断开,
mysqldump不会自动重试,建议套一层简单重试逻辑,比如用until循环或timeout控制单次最长执行时间
备份文件落地和权限校验不能省
生成的 backup.sql 是纯文本,但内容含敏感信息(如账号、结构、甚至部分数据),不能随手丢在共享目录或没权限限制的 Web 路径下。
- dump 完立即用
chmod 600 backup.sql限制读写权限 - 如果通过脚本自动化,记得检查
mysqldump的退出码:$?为 0 才算成功,非零就得报警或清理残缺文件 - 别依赖文件大小判断完整性——空库 dump 出来也可能几十 KB;更靠谱的是用
head -n 20 backup.sql | grep -q "CREATE TABLE"快速确认头部结构正常
SSH 隧道看着简单,但每条参数背后都对应一个网络或权限细节。漏掉任意一个,备份就可能静默失败,而你直到恢复时才发现。


















