核心思路是备份脚本需主动判断节点角色,仅master执行mysqldump:通过show slave status与@@read_only组合判定角色;docker环境用docker exec进入容器执行判断;可辅以keepalived vip存在性快速过滤;crontab仅负责定时触发,决策逻辑全在脚本中。

核心思路是:不依赖 crontab 自身调度“是否执行”,而是让备份脚本在每次被 cron 触发时,先主动探测当前节点角色(Master 还是 Slave),仅当确认为 Master 时才真正执行 mysqldump;否则静默退出。
这能避免从库误备份(数据滞后)、主库切换后旧备份任务仍在从库上运行、或双主脑裂下多点并发备份等风险。关键不在 crontab 写法本身,而在备份脚本的“角色感知”逻辑。
一、用 MySQL 原生命令判定主从角色
最直接可靠的方式是连接本地 MySQL 实例,查 `SHOW SLAVE STATUS` 和 `SELECT @@read_only` 组合判断:- 若
SHOW SLAVE STATUS\G有输出且Seconds_Behind_Master非 NULL → 当前是 Slave - 若
SHOW SLAVE STATUS为空(无结果集),且SELECT @@read_only返回0→ 极大概率是 Master - 更严谨做法:同时检查
SELECT VARIABLE_VALUE FROM performance_schema.global_variables WHERE VARIABLE_NAME = 'super_read_only'是否为OFF
建议封装成一行可判断的 shell 表达式:
is_master=$(mysql -Nse "SELECT CASE WHEN (SELECT COUNT(*) FROM information_schema.PROCESSLIST WHERE COMMAND='Binlog Dump') > 0 THEN '1' ELSE '0' END") # 或更通用(兼容无 performance_schema 的旧版本): is_master=$(mysql -Nse "SHOW SLAVE STATUS" | wc -l) if [ "$is_master" -eq 0 ]; then echo "[$(date)] This node is MASTER, proceeding with backup..." >> /var/log/mysql_backup.log else echo "[$(date)] Skipping: this node is SLAVE" >> /var/log/mysql_backup.log exit 0 fi
二、Docker 环境下的特殊处理(如 AlmaLinux + Docker MySQL)
若 MySQL 运行在容器中(如 mysql-master 容器),crontab 运行在宿主机,则需通过 `docker exec` 进入容器执行角色判断:# 判断容器内 MySQL 是否为主库 role=$(docker exec mysql-master mysql -Nse "SELECT IFNULL((SELECT 1 FROM information_schema.PROCESSLIST WHERE COMMAND='Binlog Dump' LIMIT 1), 0)") if [ "$role" = "1" ]; then # 是主库,执行备份(同样用 docker exec 调用 mysqldump) docker exec mysql-master mysqldump --single-transaction --all-databases | gzip > /backup/all_$(date +%Y%m%d_%H%M%S).sql.gz else exit 0 fi
注意:该容器必须已配置好 .my.cnf(挂载进容器 /root/.my.cnf),且权限为 600,避免密码暴露。
三、配合 Keepalived VIP 的辅助验证(增强可靠性)
若架构使用 Keepalived 实现 VIP 高可用(如 192.168.1.100 指向当前 Master),可在脚本中加一层网络层校验:if ip addr show | grep -q "192.168.1.100"; then echo "VIP present → likely MASTER" # 继续执行角色二次确认和备份 else echo "VIP absent → skipping backup" exit 0 fi
⚠️ 注意:VIP 存在只是旁证,不能替代 MySQL 内部状态判断,二者应组合使用——先查 VIP 快速过滤,再查 SHOW SLAVE STATUS 精确判定。
四、crontab 保持简单,只负责“定期触发”,不参与决策
crontab 条目无需复杂逻辑,保持干净即可: ```bash # 每天凌晨 2:15 执行(避开整点可能的其他任务高峰) 15 2 * * * /usr/local/scripts/backup_if_master.sh >> /var/log/mysql_backup_cron.log 2>&1 ``` 重点在于: - 脚本自身具备完整判断+执行闭环 - 日志明确记录“跳过”或“执行”,便于审计 - 备份文件名仍含时间戳,避免覆盖 - 失败时(如 MySQL 连接失败)仍需 `exit 1` 并记日志,确保告警可捕获不复杂但容易忽略。











