一、创建备份专用账户
# 创建备份账户
> create user `bkup_user`@'localhost' identified by 'StBxxxxxxx';
# 授予备份所需要的权限
> grant select,reload,lock tables,replication client,process,event,trigger,show view,execute,alter routine on *.* to `bkup_user`@'localhost';
# 刷新权限
> flush privileges;
# 验证权限
> show grants for `bkup_user`@'localhost';
二、创建备份配置文件
# 创建MySQL备份配置文件
sudo mkdir -p /work/mysql/backup
sudo tee /work/mysql/backup/backup.cnf > /dev/null <<EOF
[client]
user=bkup_user
password=StBuxxxxxxx
host=localhost
port=3306
socket=/work/mysql842/mysql/sock/mysql.sock #根据实际情况,ps -ef|grep mysqld
EOF
# 设置文件权限
sudo chmod 600 /work/mysql/backup/backup.cnf
sudo chown root:root /work/mysql/backup/backup.cnf
三、使用备份账户的备份脚本
# cat mysql/scripts/mysql_backup.sh
#!/bin/bash
# MySQL每日备份脚本(使用备份专用账户)
# 备份保留7天
# 配置参数
BACKUP_CNF="/work/mysql/backup/backup.cnf" # 备份配置文件
BACKUP_DIR="/work/mysql/mysql_backup" # 备份目录
DATE_FORMAT=$(date +%Y%m%d_%H%M%S) # 时间格式
LOG_FILE="/work/mysql/mysql_backup.log" # 日志文件
RETENTION_DAYS=7 # 保留天数
COMPRESS_LEVEL=6 # 压缩级别(1-9)
# 创建必要的目录
mkdir -p ${BACKUP_DIR}
mkdir -p $(dirname ${LOG_FILE})
# 日志函数
log() {
echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" | tee -a ${LOG_FILE}
}
# 错误处理函数
error_exit() {
log "错误: $1"
exit 1
}
# 检查MySQL连接和权限
check_mysql_connection() {
log "检查MySQL连接和备份权限..."
if ! mysql --defaults-file=${BACKUP_CNF} -e "SHOW DATABASES;" >/dev/null 2>&1; then
error_exit "无法连接到MySQL服务器,请检查备份配置文件"
fi
# 检查必要的权限
local permissions=$(mysql --defaults-file=${BACKUP_CNF} -e "SHOW GRANTS FOR CURRENT_USER()" 2>/dev/null | grep -i -E "(SELECT|RELOAD|LOCK TABLES|PROCESS)")
if [[ -z "$permissions" ]]; then
log "警告: 备份账户可能缺少某些权限"
else
log "MySQL连接和权限检查通过"
fi
}
# 获取数据库列表(排除系统数据库)
get_database_list() {
mysql --defaults-file=${BACKUP_CNF} -N -e "SHOW DATABASES;" | \
grep -v -E "(information_schema|performance_schema|sys|mysql)"
}
# 执行完整备份
perform_backup() {
local backup_file="${BACKUP_DIR}/full_backup_${DATE_FORMAT}.sql"
local compress_file="${backup_file}.gz"
log "开始MySQL完整备份..."
log "备份文件: ${compress_file}"
# 获取数据库列表
local databases=$(get_database_list)
if [[ -z "$databases" ]]; then
error_exit "未找到可备份的数据库"
fi
log "备份数据库: $databases"
# 使用mysqldump进行完整备份
if mysqldump --defaults-file=${BACKUP_CNF} \
--databases $databases \
--single-transaction \
--routines \
--events \
--triggers \
--master-data=2 \
--flush-logs \
--add-drop-database \
--complete-insert \
--hex-blob \
--max-allowed-packet=1G \
> ${backup_file} 2>>${LOG_FILE}; then
# 检查备份文件大小
local file_size=$(du -h ${backup_file} | cut -f1)
log "备份文件大小: ${file_size}"
# 压缩备份文件
log "压缩备份文件 (级别: ${COMPRESS_LEVEL})..."
if gzip -${COMPRESS_LEVEL} ${backup_file} 2>>${LOG_FILE}; then
local compressed_size=$(du -h ${compress_file} | cut -f1)
log "压缩完成: ${compressed_size}"
echo ${compress_file}
return 0
else
error_exit "备份文件压缩失败"
fi
else
error_exit "MySQL备份失败"
fi
}
# 清理旧备份
cleanup_old_backups() {
log "清理${RETENTION_DAYS}天前的备份文件..."
local old_backups=$(find ${BACKUP_DIR} -name "full_backup_*.sql.gz" -mtime +${RETENTION_DAYS})
if [[ -n "$old_backups" ]]; then
echo "$old_backups" | while read backup; do
log "删除旧备份: $(basename $backup)"
rm -f "$backup"
done
log "已清理 $(echo "$old_backups" | wc -l) 个旧备份文件"
else
log "没有需要清理的旧备份"
fi
}
# 备份验证
verify_backup() {
local backup_file=$1
if [[ ! -f "$backup_file" ]]; then
error_exit "备份文件不存在: $backup_file"
fi
log "验证备份文件完整性..."
# 检查gzip文件完整性
if ! gzip -t ${backup_file} 2>>${LOG_FILE}; then
error_exit "备份文件损坏: $backup_file"
fi
# 检查文件大小
local file_size=$(du -h ${backup_file} | cut -f1)
log "备份文件验证通过 - 大小: ${file_size}"
# 尝试列出备份中的数据库(可选,需要解压部分内容)
log "备份内容预览:"
zcat ${backup_file} | head -50 | grep -E "(Database:|CREATE DATABASE)" | head -10 >> ${LOG_FILE}
}
# 磁盘空间检查
check_disk_space() {
local backup_dir=$1
local required_space=1024 # 假设至少需要1GB空间
local available_space=$(df ${backup_dir} | awk 'NR==2 {print $4}')
available_space=$((available_space/1024)) # 转换为MB
if [[ $available_space -lt $required_space ]]; then
log "警告: 磁盘空间不足 - 可用: ${available_space}MB, 建议至少: ${required_space}MB"
return 1
else
log "磁盘空间充足: ${available_space}MB 可用"
return 0
fi
}
# 生成备份报告
generate_report() {
local status=$1
local backup_file=$2
local report_file="${BACKUP_DIR}/backup_report_${DATE_FORMAT}.txt"
{
echo "=== MySQL备份报告 ==="
echo "时间: $(date)"
echo "状态: $status"
echo "备份文件: $(basename $backup_file 2>/dev/null || echo '无')"
echo "文件大小: $(du -h $backup_file 2>/dev/null | cut -f1 || echo 'N/A')"
echo "保留策略: ${RETENTION_DAYS}天"
echo "日志文件: ${LOG_FILE}"
echo "=== 报告结束 ==="
} > ${report_file}
log "备份报告已生成: ${report_file}"
}
# 主函数
main() {
local backup_file=""
log "=== MySQL备份任务开始 ==="
# 检查磁盘空间
check_disk_space ${BACKUP_DIR}
# 检查MySQL连接
check_mysql_connection
# 执行备份
if backup_file=$(perform_backup); then
# 验证备份
verify_backup "$backup_file"
# 生成报告
generate_report "成功" "$backup_file"
else
generate_report "失败" ""
error_exit "备份过程失败"
fi
# 清理旧备份
cleanup_old_backups
log "备份任务完成: $(basename $backup_file)"
log "=== MySQL备份任务结束 ===\n"
}
# 信号处理
trap 'log "备份被用户中断"; exit 1' INT TERM
# 执行主函数
main
四、设置脚本权限和定时任务
# chmod +x /work/mysql/scripts/mysql_backup.sh
# chown root:root /work/mysql/scripts/mysql_backup.sh
创建日志目录
# mkdir -p /work/mysql
# touch /work/mysql/mysql_backup.log
# chmod 644 /work/mysql/mysql_backup.log
创建备份目录
# mkdir -p /work/mysql/mysql_backup
# chmod 755 /work/mysql/mysql_backup
添加定时任务
0 2 * * * /usr/bin/sh /work/mysql/scripts/mysql_backup.sh
五、备份账户权限说明
- SELECT 读取数据
- RELOAD 执行flush操作
- LOCK TABLES 锁定表用于一致性备份
- REPLICATION CLIENT 获取binlog位置
- PROCESS 查看运行进程
- EVENT 备份事件
- TRIGGER 备份触发器
六、手动测试备份
测试脚本
# /usr/bin/sh /work/mysql/scripts/mysql_backup.sh
查看备份文件
# ls /work/mysql/mysql_backup
查看日志
# cat /work/mysql/mysql_backup.log