MySQL 全库备份 Shell 脚本详解(排除系统库 + 安全配置)
MySQL 全库备份脚本详解:一键备份所有非系统数据库(含完整 Shell 脚本)
作者:Freed
发布时间:2025年9月10日
适用场景:MySQL 数据库日常备份、运维自动化、数据安全防护
✅ 一、前言
在生产环境中,数据库是核心资产。定期、可靠地备份数据库,是每个运维或开发人员必须掌握的基本技能。
本文提供一个通用、安全、可复用的 Shell 脚本,用于自动备份 MySQL 实例中除系统库外的所有用户数据库,并详细解释其工作原理、关键参数和优化建议,帮助你构建稳定的数据保护机制。
🛠️ 二、脚本功能说明
该脚本具备以下特性:
- ✅ 自动获取所有用户数据库(排除
information_schema
、mysql
等系统库) - ✅ 按日期创建独立备份目录(如
daily_2025-09-10
) - ✅ 逐个备份每个数据库为独立
.sql
文件 - ✅ 包含存储过程、触发器、事件调度器
- ✅ 使用
--single-transaction
保证一致性,避免锁表 - ✅ 支持远程主机、自定义端口
- ✅ 备份成功/失败状态提示
- ✅ 输出统计信息,便于监控
📜 三、完整 Shell 脚本
#!/bin/bash# ========================================
# MySQL 全库备份脚本(排除系统库)
# 作者:你的名字
# 时间:2025-09-10
# 功能:备份除系统库外的所有数据库
# ========================================# 配置参数
USER="root"
PASS="t3t9QT)yuL16Fterw"
HOST="192.168.0.2"
PORT="13306"
BACKUP_DIR="/data/backup_all_db01"
DATE=$(date +%F)# 创建按日期命名的备份目录
TARGET_DIR="$BACKUP_DIR/daily_$DATE"
mkdir -p "$TARGET_DIR"echo "[$(date +'%F %T')] 正在创建备份目录:$TARGET_DIR"# 获取所有用户数据库(排除常见系统库)
DB_LIST=$(mysql -u"$USER" -p"$PASS" -h"$HOST" -P"$PORT" -Nse \"SELECT schema_name FROM information_schema.schemata \WHERE schema_name NOT IN ('information_schema','performance_schema','mysql','sys','test')")# 检查是否有数据库需要备份
if [ -z "$DB_LIST" ]; thenecho "[$(date +'%F %T')] 错误:未找到任何需要备份的数据库!"exit 1
fiecho "[$(date +'%F %T')] 开始备份以下数据库:"
echo "--------------------------------------------------------------------------------"
echo "$DB_LIST"
echo "--------------------------------------------------------------------------------"# 循环备份每个数据库
for DB in $DB_LIST; doecho "[$(date +'%F %T')] 正在备份数据库:$DB"mysqldump \-u"$USER" \-p"$PASS" \-h"$HOST" \-P"$PORT" \--single-transaction \--routines \--triggers \--events \--quick \--set-gtid-purged=OFF \--databases "$DB" > "$TARGET_DIR/${DB}_${DATE}.sql"if [ $? -eq 0 ]; thenecho "[$(date +'%F %T')] 成功:数据库 '$DB' 已备份完成,文件路径:$TARGET_DIR/${DB}_${DATE}.sql"elseecho "[$(date +'%F %T')] 失败:数据库 '$DB' 备份失败!请检查网络、权限或磁盘空间。"fiecho ""
done# 输出最终统计
echo "--------------------------------------------------------------------------------"
echo "[$(date +'%F %T')] 所有数据库备份已完成!"
echo "备份文件保存在目录:$TARGET_DIR"
echo "共计 $(echo "$DB_LIST" | wc -w) 个数据库已处理。"
echo "--------------------------------------------------------------------------------"
🔍 四、关键参数解析
参数 | 作用说明 |
---|---|
-u / -p / -h / -P | 指定用户名、密码、主机、端口 |
--single-transaction | 使用事务确保数据一致性,适用于 InnoDB,不锁表 |
--routines | 导出存储过程和函数 |
--triggers | 导出触发器 |
--events | 导出事件调度器任务 |
--quick | 逐行读取,防止内存溢出 |
--set-gtid-purged=OFF | 不导出 GTID 信息,避免恢复时冲突(适用于非 GTID 环境) |
--databases "$DB" | 明确指定要备份的数据库 |
⚠️ 注意:
--set-gtid-purged=OFF
适用于未开启 GTID 复制的环境。若启用 GTID,请改为ON
或AUTO
。
🔒 五、安全建议:避免密码明文暴露
当前脚本将数据库密码以明文形式写入命令行,存在以下风险:
- 被
ps aux | grep mysql
命令泄露 - 被 shell 历史记录(
.bash_history
)记录 - 被其他进程通过
/proc/<pid>/cmdline
读取
✅ 推荐做法:使用 .my.cnf
配置文件 + 专用系统用户
步骤 1:创建专用系统用户(推荐)
# 创建专用备份用户
sudo adduser mysql_backup# 切换到该用户
su - mysql_backup
💡 说明:后续所有操作均在此用户下进行,实现权限隔离。
步骤 2:创建 .my.cnf
配置文件
vim ~/.my.cnf
内容如下:
[client]
user=backup_user
password=Password123!
host=192.168.0.2
port=13306
🛡️ 安全提示:
- 不要使用
root
作为数据库连接用户。- 应创建最小权限的专用账号(见下文权限配置)。
.my.cnf
文件会自动被mysql
和mysqldump
命令读取,无需额外指定。
步骤 3:设置文件权限
chmod 600 ~/.my.cnf
确保只有该用户可读写,防止其他用户窃取凭据。
步骤 4:修改脚本,去掉 -u
和 -p
# 修改前:
mysql -u"$USER" -p"$PASS" -h"$HOST" -P"$PORT" ...# 修改后:
mysql -h"$HOST" -P"$PORT" -Nse "SELECT ..."# mysqldump 同理
mysqldump -h"$HOST" -P"$PORT" ... > file.sql
此时,mysql
和 mysqldump
会自动读取 ~/.my.cnf
中的配置。
🔐 数据库用户权限配置(生产环境必备)
在 MySQL 中创建专用备份用户,遵循最小权限原则:
-- 创建用户
CREATE USER 'backup_user'@'192.168.0.2' IDENTIFIED BY 'Password123!';-- 授予备份所需权限
GRANT SELECT, LOCK TABLES, SHOW VIEW, EVENT, TRIGGER, PROCESS ON *.* TO 'backup_user'@'192.168.0.2';-- 刷新权限
FLUSH PRIVILEGES;
✅ 权限说明:
SELECT
: 读取数据LOCK TABLES
: 支持一致性备份(配合--single-transaction
)SHOW VIEW
: 导出视图定义EVENT
,TRIGGER
: 导出事件和触发器PROCESS
: 查看运行中的线程(用于监控)该用户无法修改、删除数据,极大提升安全性。
让备份脚本以 mysql_backup
用户身份运行
sudo -u mysql_backup /path/to/backup_script.sh
或在 crontab
中:
# 以 mysql_backup 用户运行
0 2 * * * sudo -u mysql_backup /data/backup_all_db01/backup_script.sh >> /data/backup_all_db01/mysql_backup.log 2>&1
⚠️ 关键提醒:
如果在脚本中仍保留了
$USER
和$PASS
变量,请务必将其从命令中移除,否则mysqldump
会优先使用命令行参数,导致.my.cnf
失效。最终目标:脚本中不再出现
-u
和-p
参数。
如果你想进一步提升安全性,可以考虑:
-
使用
mylogin.cnf
加密凭证(MySQL 5.6+ 支持)mysql_config_editor set --login-path=backup --host=192.168.0.2 --user=backup_user --password --port=13306
然后直接使用
--login-path=backup
,密码完全加密存储。 -
结合
vault
或kms
等密钥管理服务
但对于大多数场景,.my.cnf + 专用用户
已经足够安全。
🗂️ 六、备份文件结构示例
执行后生成如下结构:
/data/backup_all_db01/
└── daily_2025-09-10/├── db_user_2025-09-10.sql├── db_order_2025-09-10.sql├── db_product_2025-09-10.sql└── ...
每个数据库一个 .sql
文件,便于单独恢复。
🧩 七、如何恢复单个数据库?
mysql -u root -p database_name < /data/backup_all_db01/daily_2025-09-10/database_name_2025-09-10.sql
🕒 八、结合 crontab 实现每日自动备份
添加定时任务(每天凌晨 2 点执行):
crontab -e
写入:
0 2 * * * /data/backup_all_db01/backup_script.sh >> /data/backup_all_db01/mysql_backup.log 2>&1
🧹 九、进阶建议
-
压缩备份文件:使用
gzip
减少磁盘占用gzip "$TARGET_DIR/${DB}_${DATE}.sql"
-
清理旧备份:保留最近 7 天
find $BACKUP_DIR -name "daily_*" -type d -mtime +7 -exec rm -rf {} \;
-
发送通知:备份完成后通过邮件或企业微信通知管理员。
-
校验完整性:检查
.sql
文件是否为空或包含错误。 -
异地备份:用
rsync
或scp
将备份同步到其他服务器或对象存储
✅ 十、总结
本文提供的脚本是一个高度实用、可直接投入生产环境的 MySQL 全库备份方案。它不仅功能完整,而且结构清晰,易于维护和扩展。
通过合理配置和定期执行,你可以有效防范数据丢失风险,为业务稳定运行保驾护航。
💡 小贴士
- 如果你使用的是 MariaDB,该脚本同样适用。
- ⚠️ 对于超大数据库(>100GB),建议使用
Percona XtraBackup
进行物理备份,避免逻辑备份性能瓶颈。