环境说明:MySQL 5.7 / 8.0 通用(会标注差异) 备份工具:mysqldump做全量备份,binlog 做增量备份(不是 xtrabackup 增量,符合题目要求) 备份库:company目录规划:
- 全量备份:
/backup/mysql/full/ - 增量 binlog 备份:
/backup/mysql/increment/调度:crontab 核心逻辑:
- 周六 0 点:全量 mysqldump 导出 company 库,同时刷新 binlog,作为增量起点
- 每日凌晨 1 点:把上一次刷新之后新增的 binlog 复制到增量目录
- 恢复:先导入最近一次全量备份,再按顺序回放增量 binlog
⚠️ 前提:MySQL 必须开启 binlog!
一、前置准备(必做)
1. 开启 binlog(my.cnf/my.ini)
# /etc/my.cnf [mysqld] server-id=1 log-bin=mysql-bin binlog-format=ROW expire_logs_days=7 # 5.7;8.0用 binlog_expire_logs_seconds=604800 datadir=/var/lib/mysql修改后重启 mysql
systemctl restart mysqld验证 binlog 开启
mysql -uroot -p'你的root密码' -e "show variables like 'log_bin';"ON 代表开启成功
2. 创建备份目录
mkdir -p /backup/mysql/full /backup/mysql/increment chown mysql:mysql /backup/mysql -R chmod 700 /backup/mysql3. 创建备份专用账号(推荐,不要用 root)
CREATE USER 'bkuser'@'localhost' IDENTIFIED BY 'Bk@123456'; GRANT SELECT,RELOAD,LOCK TABLES,REPLICATION CLIENT,EVENT ON *.* TO 'bkuser'@'localhost'; FLUSH PRIVILEGES;4. 记录信息
- 备份用户:
bkuser - 密码:
Bk@123456 - 数据库:
company
脚本里可以写到配置项,生产建议用.my.cnf免密,避免明文密码
免密配置优化(可选,企业规范)
cat > /root/.my.cnf <<EOF [client] user=bkuser password=Bk@123456 socket=/var/lib/mysql/mysql.sock EOF chmod 600 /root/.my.cnf后续 mysqldump 不用写-u -p
二、脚本 1:全量备份脚本mysql_full_backup.sh
功能:mysqldump 备份 company 库,压缩,刷新 binlog,记录当前 binlog 文件名(增量恢复起点)
#!/bin/bash # mysql_full_backup.sh # 全量备份 company 库 # 配置 DB_NAME="company" FULL_BACKUP_DIR="/backup/mysql/full" DATE=$(date +%Y%m%d_%H%M%S) BK_FILE="${FULL_BACKUP_DIR}/${DB_NAME}_full_${DATE}.sql.gz" BINLOG_RECORD="${FULL_BACKUP_DIR}/last_binlog.txt" # 备份 mysqldump -uroot -pRoot@123456 --single-transaction --master-data=2 --databases ${DB_NAME} | gzip > ${BK_FILE} # 判断备份是否成功 if [ $? -eq 0 ];then echo "【全量备份成功】${BK_FILE}" # 刷新binlog,开启新日志,后续增量只拷贝新binlog mysql -uroot -pRoot@123456 -e "FLUSH BINARY LOGS;" # 记录当前最新binlog文件名(增量起点) NEW_BINLOG=$(mysql -uroot -pRoot@123456 -e "show master status\G" | grep File | awk '{print $2}') echo ${NEW_BINLOG} > ${BINLOG_RECORD} else echo "【全量备份失败】" exit 1 fi # 清理7天前全量备份(按需) find ${FULL_BACKUP_DIR} -name "*.sql.gz" -mtime +7 -delete赋权
chmod +x /usr/local/bin/mysql_full_backup.sh参数说明:--single-transaction:InnoDB 热备,不加锁(推荐)--master-data=2:在备份 sql 中注释记录 binlog 位置,恢复参考FLUSH BINARY LOGS:切割 binlog,增量从这个新文件开始
三、脚本 2:增量备份脚本mysql_inc_backup.sh
增量本质:拷贝【上次全量刷新之后】产生的 binlog 文件到增量目录,binlog 本身就是增量日志
#!/bin/bash # mysql_inc_backup.sh # binlog增量备份 FULL_BACKUP_DIR="/backup/mysql/full" INC_BACKUP_DIR="/backup/mysql/increment" BINLOG_RECORD="${FULL_BACKUP_DIR}/last_binlog.txt" # mysql binlog存放路径,和my.cnf一致 BINLOG_DIR="/var/lib/mysql" # 判断全量备份是否已经执行过(必须有起点binlog记录) if [ ! -f ${BINLOG_RECORD} ];then echo "错误:没有找到全量备份的binlog起点文件,请先执行一次全量备份!" exit 1 fi START_BINLOG=$(cat ${BINLOG_RECORD}) # 获取当前所有binlog列表 BINLOG_LIST=$(mysql -uroot -pRoot@123456 -e "show binary logs;" | awk '{print $1}' | grep -v Log_name) # 循环拷贝大于等于START_BINLOG的binlog到增量目录 for bl in ${BINLOG_LIST};do if [[ "${bl}" > "${START_BINLOG}" || "${bl}" == "${START_BINLOG}" ]];then cp -p ${BINLOG_DIR}/${bl} ${INC_BACKUP_DIR}/ fi done echo "【增量binlog拷贝完成,起点:${START_BINLOG}】" # 清理14天前增量日志 find ${INC_BACKUP_DIR} -name "mysql-bin.*" -mtime +14 -delete赋权
chmod +x /usr/local/bin/mysql_inc_backup.sh重点: 这个方案是标准企业方案:全量做基线,增量是 binlog 日志每天 01 点执行,把新增 binlog 同步出来; binlog 里记录了 INSERT/UPDATE/DELETE,就是增量数据。
四、手动测试备份(先手动跑一遍,确认脚本没问题再加定时)
# 先手动执行全量 /usr/local/bin/mysql_full_backup.sh # 查看生成文件 ls /backup/mysql/full/ cat /backup/mysql/full/last_binlog.txt # 手动执行增量 /usr/local/bin/mysql_inc_backup.sh ls /backup/mysql/increment/五、配置 Crontab 定时任务
crontab -e写入:
# 每周六 00:00 全量备份 0 0 * * 6 /usr/local/bin/mysql_full_backup.sh >> /var/log/mysql_full_bk.log 2>&1 # 每天 01:00 增量binlog备份 0 1 * * * /usr/local/bin/mysql_inc_backup.sh >> /var/log/mysql_inc_bk.log 2>&1查看定时
crontab -l日志:
/var/log/mysql_full_bk.log/var/log/mysql_inc_bk.log
时间规则:分 时 日 月 周0 0 * * 6= 周六 0 点
六、数据恢复完整流程(重点)
恢复场景:company 数据库损坏,需要恢复到最新状态 恢复顺序:先恢复全量备份 → 按顺序回放 binlog 增量⚠️ 恢复前:停业务,锁库,禁止新写入;建议先把所有备份文件另外拷贝一份,防止恢复操作破坏备份!
步骤 1:停止业务,进入维护模式,清空损坏库(演示)
DROP DATABASE IF EXISTS company; CREATE DATABASE company;步骤 2:恢复最近一次【全量备份】
找到最新的全量压缩包,解压导入
# 解压导入 gzip -d -c /backup/mysql/full/company_full_20261026_000000.sql.gz | mysql company此时数据恢复到【周六 0 点全量备份时刻】
步骤 3:回放增量 binlog(核心增量恢复)
找到增量目录下从起点开始的所有 binlog 文件,按文件名顺序回放!
# 示例:起点是 mysql-bin.000120 mysqlbinlog /backup/mysql/increment/mysql-bin.000120 /backup/mysql/increment/mysql-bin.000121 | mysql companymysqlbinlog 回放必须按顺序!序号从小到大 如果只需要恢复到某个时间点,可以加时间参数:
mysqlbinlog --no-defaults --stop-datetime="2026-10-26 10:00:00" mysql-bin.000120 | mysql -uroot -pRoot@123456 company步骤 4:校验数据
use company; show tables; select * from 业务表;核对增量阶段新增 / 修改的数据是否回来。
七、常见故障 & 思考题
1. 增量脚本提示没有last_binlog.txt
原因:还没跑过全量备份,没有基线。必须先跑全量,再跑增量。
2. mysqldump --single-transaction 对 MyISAM 无效
MyISAM 需要 --lock-tables,InnoDB 推荐 --single-transaction 热备
3. binlog 文件打不开、报错
权限问题,mysqlbinlog 读取 binlog 需要读权限;不要直接修改 binlog
4. 恢复顺序颠倒导致数据错乱
binlog 是顺序日志,必须从小到大回放
5. 增量脚本中mysql命令未指定密码,执行show binary logs;时报 1045 拒绝访问;虽然脚本打印了增量完成提示,但获取 binlog 列表失败,脚本实际失效。
解决办法:要么 mysql 命令带上账号密码,要么配置/root/.my.cnf实现免密登录。