MySQL数据库远程备份是保障数据安全的核心环节,通过SSH隧道加密传输可以规避公网明文传输的安全隐患,配合自动化脚本还能实现定时无人值守备份,大幅降低运维成本。本文将从环境准备到最终定时任务配置,完整讲解整个实现流程。

环境准备
开始配置前需要确认以下环境信息:
- 本地备份服务器:用于执行备份脚本,存放备份文件,假设IP为192.168.0.10
- 远程MySQL服务器:需要备份的数据库所在服务器,假设IP为192.168.0.20,MySQL端口3306,数据库用户backup_user,密码Backup@123
- 两台服务器均开启SSH服务,且网络互通
配置SSH密钥认证
为避免脚本中明文存储SSH密码,优先配置SSH密钥对实现免密登录:
生成密钥对
在本地备份服务器执行以下命令生成密钥对:
# 生成rsa密钥对,一路回车即可,默认存放在~/.ssh目录 ssh-keygen -t rsa
拷贝公钥到远程服务器
将本地生成的公钥拷贝到远程MySQL服务器的授权列表中:
# 替换远程服务器用户名和IP ssh-copy-id root@192.168.0.20
执行完成后,尝试SSH登录远程服务器,无需输入密码即可登录说明配置成功:
ssh root@192.168.0.20
搭建SSH隧道
SSH隧道可以将本地端口映射到远程MySQL服务器的3306端口,让本地可以直接通过本地端口访问远程MySQL服务,所有传输数据都会被SSH加密。
手动测试SSH隧道
在本地备份服务器执行以下命令建立隧道:
# -L 本地端口:远程地址:远程端口 -N 不执行远程命令 -f 后台运行 ssh -L 13306:127.0.0.1:3306 -N -f root@192.168.0.20
命令执行后,本地13306端口就会映射到远程MySQL的3306端口,测试连接:
mysql -h 127.0.0.1 -P 13306 -u backup_user -pBackup@123
能正常进入MySQL命令行说明隧道搭建成功。
隧道保活配置
默认SSH隧道长时间无传输会自动断开,需要配置保活参数,修改本地SSH客户端配置:
# 编辑SSH客户端配置 vim ~/.ssh/config
添加以下内容:
Host mysql_remote
HostName 192.168.0.20
User root
LocalForward 13306 127.0.0.1:3306
ServerAliveInterval 60
ServerAliveCountMax 3
之后可以直接用ssh -N -f mysql_remote建立保活隧道。
编写MySQL远程备份脚本
接下来编写完整的备份脚本,实现隧道建立、数据库备份、文件清理、隧道关闭的全流程。
#!/bin/bash
# MySQL远程备份脚本,通过SSH隧道实现加密传输
# 配置参数
REMOTE_MYSQL_IP="127.0.0.1" # SSH隧道映射的本地地址
REMOTE_MYSQL_PORT=13306 # 隧道映射的本地端口
MYSQL_USER="backup_user" # MySQL备份用户
MYSQL_PASSWORD="Backup@123" # MySQL备份用户密码
BACKUP_DIR="/data/mysql_backup" # 本地备份文件存放目录
BACKUP_DATE=$(date +%Y%m%d_%H%M%S) # 备份时间戳
SSH_HOST="192.168.0.20" # 远程SSH服务器地址
SSH_USER="root" # SSH登录用户
TUNNEL_ALIVE_CHECK_PORT=13306 # 隧道检测端口
# 创建备份目录
mkdir -p ${BACKUP_DIR}
# 检查SSH隧道是否已经存在
check_tunnel() {
if netstat -tuln | grep ":${TUNNEL_ALIVE_CHECK_PORT}" > /dev/null; then
return 0
else
return 1
fi
}
# 建立SSH隧道
build_tunnel() {
echo "开始建立SSH隧道..."
# 如果已经存在隧道先关闭
if check_tunnel; then
echo "检测到已有隧道,先关闭旧隧道"
pkill -f "ssh -L ${TUNNEL_ALIVE_CHECK_PORT}:127.0.0.1:3306"
sleep 2
fi
# 建立新隧道
ssh -L ${TUNNEL_ALIVE_CHECK_PORT}:127.0.0.1:3306 -N -f ${SSH_USER}@${SSH_HOST}
sleep 3
if check_tunnel; then
echo "SSH隧道建立成功"
else
echo "SSH隧道建立失败,退出脚本"
exit 1
fi
}
# 执行备份
do_backup() {
echo "开始执行数据库备份..."
# 备份所有数据库,排除系统库可根据需求调整
mysqldump -h ${REMOTE_MYSQL_IP} -P ${REMOTE_MYSQL_PORT} -u ${MYSQL_USER} -p${MYSQL_PASSWORD} --all-databases > ${BACKUP_DIR}/full_backup_${BACKUP_DATE}.sql
# 检查备份是否成功
if [ $? -eq 0 ]; then
echo "备份成功,文件保存在:${BACKUP_DIR}/full_backup_${BACKUP_DATE}.sql"
# 压缩备份文件
gzip ${BACKUP_DIR}/full_backup_${BACKUP_DATE}.sql
echo "备份文件已压缩为:${BACKUP_DIR}/full_backup_${BACKUP_DATE}.sql.gz"
else
echo "备份失败,请检查配置"
exit 1
fi
}
# 清理7天前的旧备份
clean_old_backup() {
echo "开始清理7天前的旧备份文件..."
find ${BACKUP_DIR} -name "*.sql.gz" -mtime +7 -exec rm -f {} ;
echo "旧备份清理完成"
}
# 关闭SSH隧道
close_tunnel() {
echo "开始关闭SSH隧道..."
pkill -f "ssh -L ${TUNNEL_ALIVE_CHECK_PORT}:127.0.0.1:3306"
if ! check_tunnel; then
echo "SSH隧道已关闭"
else
echo "SSH隧道关闭失败,请手动检查"
fi
}
# 执行主流程
build_tunnel
do_backup
clean_old_backup
close_tunnel
echo "远程备份流程执行完成"
给脚本添加执行权限:
chmod +x /data/scripts/mysql_remote_backup.sh
手动执行脚本测试,确认备份文件正常生成:
/data/scripts/mysql_remote_backup.sh
设置自动化定时任务
通过crontab设置定时执行备份脚本,实现每天凌晨2点自动备份:
# 编辑crontab配置 crontab -e
添加以下内容:
0 2 * * * /data/scripts/mysql_remote_backup.sh >> /data/mysql_backup/backup.log 2>&1
保存后重启crontab服务让配置生效:
# CentOS/RHEL系统 systemctl restart crond # Ubuntu/Debian系统 systemctl restart cron
可以通过以下命令查看crontab任务是否添加成功:
crontab -l
常见问题排查
| 问题现象 | 可能原因 | 解决方法 |
|---|---|---|
| SSH隧道建立失败 | 密钥认证未配置成功、远程SSH服务未开启、网络不通 | 重新检查密钥配置,测试SSH登录,确认网络连通性 |
| 备份时连接MySQL失败 | 隧道未正常建立、MySQL用户权限不足、密码错误 | 检查隧道状态,确认MySQL用户有备份权限,核对密码 |
| 定时任务未执行 | crontab服务未启动、脚本路径错误、脚本无执行权限 | 启动crontab服务,检查脚本路径和权限,查看日志排查 |