Linux服务器MySql备份脚本

一、前置条件

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 天前的旧备份(根据脚本配置)

记录日志便于审计。

 

发表评论

称呼 *
联系方式 * 方便与您联系,不会对外显示。
内容
验证码