一、前置条件
1.服务器需安装MySql客户端工具。
2.备份用的MySql账号要有响应权限。
二、备份脚本
1.备份所有数据库
#!/bin/bash
# MySQL 配置
MYSQL_USER="******"
MYSQL_PASS="******" # 修改为你的 MySQL 密码
MYSQL_HOST="******"
MYSQL_PORT="3306"
# 备份配置
BACKUP_ROOT_DIR="/web/db_bak" # 修改为你想存放备份的根目录
DATE=$(date +%Y-%m-%d)
BACKUP_DIR="$BACKUP_ROOT_DIR/$DATE"
# 保留天数(自动删除 N 天前的备份)
RETENTION_DAYS=7
# 日志
LOG_FILE="$BACKUP_ROOT_DIR/backup.log"
# 创建备份目录
mkdir -p "$BACKUP_DIR"
# 获取所有数据库列表(排除系统库可选)
DATABASES=$(mysql -h"$MYSQL_HOST" -P"$MYSQL_PORT" -u"$MYSQL_USER" -p"$MYSQL_PASS" -e "SHOW DATABASES;" | grep -Ev "(information_schema|performance_schema|sys|mysql)")
# 日志函数
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
log "开始备份 MySQL 数据库..."
for db in $DATABASES; do
BACKUP_FILE="$BACKUP_DIR/${db}_${DATE}.sql.gz"
log "正在备份数据库: $db"
mysqldump -h"$MYSQL_HOST" -P"$MYSQL_PORT" -u"$MYSQL_USER" -p"$MYSQL_PASS" \
--single-transaction --routines --triggers --databases "$db" | gzip > "$BACKUP_FILE"
if [ $? -eq 0 ]; then
log "备份成功: $BACKUP_FILE"
else
log "备份失败: $db"
fi
done
# 删除 $RETENTION_DAYS 天前的备份目录
find "$BACKUP_ROOT_DIR" -maxdepth 1 -type d -name "20*" -mtime +$RETENTION_DAYS -exec rm -rf {} \; 2>>"$LOG_FILE"
log "过期备份已清理(>$RETENTION_DAYS 天)"
log "MySQL 备份完成。"
2.备份指定数据库
#!/bin/bash
# MySQL 配置
#MYSQL_USER="******" # 写到/root/.my.cnf文件
#MYSQL_PASS="******" # 写到/root/.my.cnf文件
MYSQL_HOST="******"
MYSQL_PORT="3306"
MYSQL_DB_NAME="******" #数据库名称
# 备份配置
BACKUP_ROOT_DIR="/web/db_bak" # 修改为你想存放备份的根目录
DATE=$(date +%Y-%m-%d)
BACKUP_DIR="$BACKUP_ROOT_DIR/$DATE"
BACKUP_FILE="$BACKUP_DIR/${MYSQL_DB_NAME}_${DATE}.sql.gz"
# 保留天数(自动删除 N 天前的备份)
RETENTION_DAYS=7
# 日志文件
LOG_FILE="$BACKUP_ROOT_DIR/backup.log"
# 确保备份根目录存在
mkdir -p "$BACKUP_DIR"
# 日志函数
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
log "开始备份数据库: $MYSQL_DB_NAME"
# 执行备份并压缩
mysqldump -h"$MYSQL_HOST" -P"$MYSQL_PORT" -u"$MYSQL_USER" -p"$MYSQL_PASS" \
--single-transaction --set-gtid-purged=OFF --routines --triggers "$MYSQL_DB_NAME" | gzip > "$BACKUP_FILE"
if [ $? -eq 0 ]; then
log "备份成功: $BACKUP_FILE"
else
log "备份失败:$MYSQL_DB_NAME"
exit 1
fi
# 删除 $RETENTION_DAYS 天前的旧备份目录
find "$BACKUP_ROOT_DIR" -maxdepth 1 -type d -name "20*" -mtime +$RETENTION_DAYS -exec rm -rf {} \; 2>>"$LOG_FILE"
log "已清理 $RETENTION_DAYS 天前的旧备份"
log "备份任务完成。"
三、常见问题
mysqldump参数含义
参数 | 含义 |
---|---|
-h"$MYSQL_HOST" |
指定 MySQL 服务器的主机地址。$MYSQL_HOST 是变量,值为 "localhost" 。如果是本地可省略。 |
-P"$MYSQL_PORT" |
指定端口号(注意是大写 P)。MySQL 默认是 3306 。变量 $MYSQL_PORT 替换为 3306 。 |
-u"$MYSQL_USER" |
指定登录用户名。$MYSQL_USER 通常是 root 或其他有权限的用户。 |
-p"$MYSQL_PASS" |
指定密码(小写 p)。$MYSQL_PASS 是你的密码。⚠️ 注意:-p 和密码之间不能有空格,写成 -p $MYSQL_PASS 会出错。 |
备份选项(关键参数)
参数 | 作用说明 |
---|---|
--single-transaction |
在导出开始时启动一个事务,确保数据一致性(尤其对 InnoDB 表),避免锁表。✅ 推荐用于在线业务。 |
--routines |
包含存储过程(Stored Procedures)和函数(Functions)的定义。 |
--triggers |
包含每个表的触发器(Triggers)定义。 |
警告 1:
mysqldump: [Warning] Using a password on the command line interface can be insecure.
含义:
在命令行中直接使用 -p"$MYSQL_PASS"的方式传密码,会导致密码可能被:
记录在 shell 历史(~/.bash_history)
被ps aux | grep mysqldump命令看到(短暂暴露)
虽然脚本中用变量有一定缓解,但仍不推荐用于高安全环境。
解决方案:使用 .my.cnf
配置文件(推荐)
vim /root/.my.cnf
写入内容:
[client]
user=数据库用户名
password=你的实际密码
host=localhost
port=3306
保存后设置权限(关键!):
chmod 600 /root/.my.cnf
然后修改你的备份脚本中的 mysqldump
命令,去掉 -u
和 -p
参数,此时 MySQL 会自动读取 .my.cnf
,不再出现密码警告。
警告 2:
Warning: A partial dump from a server that has GTIDs will by default include the GTIDs of all transactions...
If you don't want to restore GTIDs, pass --set-gtid-purged=OFF.
含义:
你的 MySQL 启用了 GTID(Global Transaction ID),这是一种主从复制中用来唯一标识事务的机制。
当你只备份单个数据库(非 --all-databases)时,MySQL 默认会导出这些 GTID 信息。但在恢复时,如果目标库没有开启 GTID 或配置不同,可能会出错。
解决方案:明确关闭 GTID 导出(适用于大多数单库备份场景)
在mysqldump 命令中添加:
--set-gtid-purged=OFF
优化后的完整命令(推荐使用)
mysqldump -h"$MYSQL_HOST" -P"$MYSQL_PORT" \
--single-transaction \
--routines \
--triggers \
--events \
--set-gtid-purged=OFF \
"$DATABASE_NAME" | gzip > "$BACKUP_FILE"
四、添加系统定时任务
步骤 1:确保备份脚本已存在且可执行
假设你的备份脚本路径是:/root/mysql_backup.sh
请确认:(1)脚本内容正确。(2)已添加执行权限
步骤 2:编辑 root 用户的定时任务(crontab)
以 root 用户身份运行:
crontab -e
注意:必须用 root 编辑,因为脚本可能涉及敏感操作和目录权限。
步骤 3:添加定时任务(每天 00:00 执行)
在打开的编辑器中,添加以下一行:
0 0 * * * /root/mysql_backup.sh >> /data/backup/mysql/cron.log 2>&1
含义解释:
时间段 | 含义 |
---|---|
0 |
分钟(第 0 分钟) |
0 |
小时(00:00,即午夜) |
* |
每天 |
* |
每月 |
* |
每周几(0-7,0 和 7 都是周日) |
👉 所以 0 0 * * *
= 每天凌晨 00:00 执行一次
步骤 4:保存并退出
如果你用的是 vim,按 Esc,输入 :wq 回车保存。
如果是 nano,按 Ctrl+O 写入,回车,再按 Ctrl+X 退出。
步骤 5:验证定时任务是否生效
查看当前 root 的定时任务:
crontab -l
最终效果
从明天开始,每天 00:00 系统会自动执行:
备份数据库。
压缩为 .sql.gz。
存放到 /data/backup/mysql/年-月-日/。
自动清理 7 天前的旧备份(根据脚本配置)
记录日志便于审计。
发表评论