MySQL增量备份是指只备份自上次备份以来发生变化的数据,相比全量备份可以节省存储空间和备份时间。增量备份通常基于二进制日志(binlog)实现。
#!/bin/bash
# MySQL增量备份脚本
# 需要先开启MySQL的binlog功能
# 配置参数
MYSQL_USER="backup_user"
MYSQL_PASSWORD="your_password"
MYSQL_HOST="localhost"
BACKUP_DIR="/data/backups/mysql/incremental"
DATE=$(date +%Y%m%d_%H%M%S)
LOG_FILE="/var/log/mysql_incremental_backup.log"
# 创建备份目录
mkdir -p ${BACKUP_DIR}/${DATE}
# 获取当前binlog文件及位置
BINLOG_INFO=$(mysql -u${MYSQL_USER} -p${MYSQL_PASSWORD} -h${MYSQL_HOST} -e "SHOW MASTER STATUS" | awk 'NR==2 {print $1, $2}')
if [ -z "$BINLOG_INFO" ]; then
echo "[$(date +'%Y-%m-%d %H:%M:%S')] Error: Cannot get binlog info" >> ${LOG_FILE}
exit 1
fi
BINLOG_FILE=$(echo $BINLOG_INFO | awk '{print $1}')
BINLOG_POS=$(echo $BINLOG_INFO | awk '{print $2}')
# 刷新日志,生成新的binlog文件
mysqladmin -u${MYSQL_USER} -p${MYSQL_PASSWORD} -h${MYSQL_HOST} flush-logs
# 备份旧的binlog文件
BINLOG_DIR=$(mysql -u${MYSQL_USER} -p${MYSQL_PASSWORD} -h${MYSQL_HOST} -e "SHOW VARIABLES LIKE 'log_bin_basename'" | awk 'NR==2 {print $2}')
BINLOG_DIR=$(dirname $BINLOG_DIR)
# 获取需要备份的binlog文件列表
BINLOGS=$(ls -tr ${BINLOG_DIR}/${BINLOG_FILE%.*}* | grep -v "${BINLOG_FILE}$")
for binlog in $BINLOGS; do
cp $binlog ${BACKUP_DIR}/${DATE}/
if [ $? -eq 0 ]; then
echo "[$(date +'%Y-%m-%d %H:%M:%S')] Copied $binlog to ${BACKUP_DIR}/${DATE}" >> ${LOG_FILE}
else
echo "[$(date +'%Y-%m-%d %H:%M:%S')] Error copying $binlog" >> ${LOG_FILE}
fi
done
# 记录本次备份信息
echo "${DATE} ${BINLOG_FILE} ${BINLOG_POS}" >> ${BACKUP_DIR}/binlog_index.txt
# 删除过期备份(保留最近7天)
find ${BACKUP_DIR} -type d -mtime +7 -exec rm -rf {} \;
echo "[$(date +'%Y-%m-%d %H:%M:%S')] Incremental backup completed" >> ${LOG_FILE}
#!/bin/bash
# MySQL增量备份脚本(使用mysqlbinlog工具)
# 配置参数
MYSQL_USER="backup_user"
MYSQL_PASSWORD="your_password"
MYSQL_HOST="localhost"
BACKUP_DIR="/data/backups/mysql/incremental"
DATE=$(date +%Y%m%d_%H%M%S)
LOG_FILE="/var/log/mysql_incremental_backup.log"
LAST_BACKUP_FILE="${BACKUP_DIR}/last_backup_info"
# 创建备份目录
mkdir -p ${BACKUP_DIR}/${DATE}
# 获取当前binlog信息
BINLOG_INFO=$(mysql -u${MYSQL_USER} -p${MYSQL_PASSWORD} -h${MYSQL_HOST} -e "SHOW MASTER STATUS" | awk 'NR==2 {print $1, $2}')
if [ -z "$BINLOG_INFO" ]; then
echo "[$(date +'%Y-%m-%d %H:%M:%S')] Error: Cannot get binlog info" >> ${LOG_FILE}
exit 1
fi
CURRENT_BINLOG=$(echo $BINLOG_INFO | awk '{print $1}')
CURRENT_POS=$(echo $BINLOG_INFO | awk '{print $2}')
# 读取上次备份的位置
if [ -f "$LAST_BACKUP_FILE" ]; then
LAST_BACKUP_INFO=$(cat $LAST_BACKUP_FILE)
LAST_BINLOG=$(echo $LAST_BACKUP_INFO | awk '{print $1}')
LAST_POS=$(echo $LAST_BACKUP_INFO | awk '{print $2}')
else
# 如果是第一次备份,则从当前binlog的开头开始
LAST_BINLOG=$CURRENT_BINLOG
LAST_POS=4 # binlog文件通常从位置4开始
fi
# 生成增量备份
BACKUP_FILE="${BACKUP_DIR}/${DATE}/incremental_${DATE}.sql"
# 使用mysqlbinlog工具导出增量数据
mysqlbinlog --start-position=${LAST_POS} --stop-position=${CURRENT_POS} \
-u${MYSQL_USER} -p${MYSQL_PASSWORD} -h${MYSQL_HOST} \
${LAST_BINLOG} > ${BACKUP_FILE}
if [ $? -eq 0 ]; then
echo "[$(date +'%Y-%m-%d %H:%M:%S')] Incremental backup created: ${BACKUP_FILE}" >> ${LOG_FILE}
# 记录本次备份位置
echo "${CURRENT_BINLOG} ${CURRENT_POS}" > ${LAST_BACKUP_FILE}
else
echo "[$(date +'%Y-%m-%d %H:%M:%S')] Error creating incremental backup" >> ${LOG_FILE}
exit 1
fi
# 压缩备份文件
gzip ${BACKUP_FILE}
# 删除过期备份(保留最近7天)
find ${BACKUP_DIR} -type d -mtime +7 -exec rm -rf {} \;
echo "[$(date +'%Y-%m-%d %H:%M:%S')] Incremental backup completed" >> ${LOG_FILE}
准备工作:
log_bin=mysql-bin
)sql
CREATE USER 'backup_user'@'localhost' IDENTIFIED BY 'your_password';
GRANT RELOAD, SUPER, REPLICATION CLIENT ON *.* TO 'backup_user'@'localhost';
GRANT SELECT ON mysql.* TO 'backup_user'@'localhost';
FLUSH PRIVILEGES;
脚本部署:
mysql_incremental_backup.sh
chmod +x mysql_incremental_backup.sh
bash
0 2 * * * /path/to/mysql_incremental_backup.sh
恢复数据:
bash
mysql -u root -p < full_backup.sql
mysqlbinlog incremental_backup.000001 | mysql -u root -p
mysqlbinlog incremental_backup.000002 | mysql -u root -p
对于生产环境,可以考虑使用专业的备份工具: - Percona XtraBackup(支持热备份) - MySQL Enterprise Backup - mydumper/myloader
这些工具提供了更完善的备份恢复功能,适合大规模生产环境使用。