堡垒机环境下迁移MySQL数据库遇xmalloc内存分配失败问题排查
数据库迁移内存不足问题:根源诊断与修复方案
没错,你的脚本确实是把整个2.7G的数据库dump文件全部加载到内存里了,这直接导致了2G内存服务器的OOM(内存不足)错误,问题就出在堡垒机2上的forwardDbMigration.sh脚本里。
问题根源分析
看一下forwardDbMigration.sh里的关键行:
ssh -i ~/.ssh/key.pem ubuntu@<ip address> "mysql -h <db host> -u <db user> -p<db password> <new db name>" < $(< /dev/stdin)
这里的$(< /dev/stdin)是bash的命令替换语法,它会一次性把标准输入的所有内容读取到内存中,生成一个临时字符串后再作为文件内容重定向给ssh命令。你的dump文件有2.7G,远大于服务器的2G内存,内存直接被撑爆是必然的。
修复方案
我们需要改成流式传输,让数据从源端一点点传到目标端,全程不把整个dump文件加载到内存里。修改后的forwardDbMigration.sh非常简单:
#!/bin/bash ssh -i ~/.ssh/key.pem ubuntu@<ip address> "mysql -h <db host> -u <db user> -p<db password> <new db name>"
如果你想明确指定从标准输入读取,也可以写成:
#!/bin/bash ssh -i ~/.ssh/key.pem ubuntu@<ip address> "mysql -h <db host> -u <db user> -p<db password> <new db name>" < /dev/stdin
原理很简单:ssh默认会把本地进程的标准输入直接转发给远程执行的命令,而mysql本身就支持从标准输入读取SQL语句执行。这样整个链路是:mysqldump → 管道 → 堡垒机1的ssh → 网络 → 堡垒机2的ssh → 远程mysql
全程都是流式处理,内存占用只有每个环节的缓冲区大小,完全不会触及2G的内存上限。
额外优化建议
- 启用传输压缩:给
mysqldump加上--compress参数,减少网络传输的数据量,既加快迁移速度,也能降低中间环节的内存压力:ssh -i ~/.ssh/key.pem ubuntu@<ipaddress> "mysqldump --compress -h <db host> -u <db user> -p<db password> <orig db name>" | ssh -i ~/.ssh/key.pem ubuntu@<ipaddress> "/home/ubuntu/forwardDbMigration.sh" - 避免明文密码:把数据库的用户名和密码放到
~/.my.cnf配置文件里,不用在命令行暴露敏感信息。比如在堡垒机1的ubuntu用户下创建~/.my.cnf:
然后[mysqldump] user=<db user> password=<db password> host=<db host>mysqldump命令可以简化成mysqldump <orig db name>;目标服务器的mysql端也可以用同样的方式配置~/.my.cnf,让命令更简洁安全。
内容的提问来源于stack exchange,提问作者JBaczuk
相关产品推荐
相关产品推荐

