MySQL二进制日志(binlog)是数据库运行过程中产生的记录所有数据修改操作的日志文件,在数据库恢复、主从复制、数据审计等场景中都有重要作用。但如果不对二进制日志进行合理管理,日志文件会持续累积占用磁盘空间,甚至可能导致磁盘满影响数据库正常运行。编写一套高效的二进制日志管理脚本,能够实现日志的自动化清理、备份和状态监控,大幅降低人工运维成本。

MySQL二进制日志管理核心需求
在编写管理脚本前,需要先明确二进制日志管理的核心需求,避免脚本功能冗余或缺失:
- 过期日志自动清理:删除超过保留时长的二进制日志,释放磁盘空间
- 重要日志定期备份:将近期二进制日志备份到指定存储路径,避免误删后无法恢复数据
- 日志状态监控:定期检查二进制日志的占用空间、生成频率,异常时触发告警
- 操作安全性保障:清理日志前校验当前数据库状态,避免删除正在使用的日志文件
脚本编写前的准备工作
编写脚本前需要先完成以下基础配置,确保脚本可以正常调用MySQL相关命令:
1. 配置MySQL环境变量
确保mysql、mysqlbinlog命令已经加入系统PATH,或者脚本中直接指定命令的完整路径,比如/usr/local/mysql/bin/mysql。
2. 创建专用管理用户
不建议使用root用户执行脚本,创建一个仅拥有二进制日志查看、清理权限的专用用户,降低操作风险:
-- 创建管理用户 CREATE USER 'binlog_admin'@'localhost' IDENTIFIED BY 'your_password'; -- 授予二进制日志相关权限 GRANT RELOAD, REPLICATION CLIENT ON *.* TO 'binlog_admin'@'localhost'; FLUSH PRIVILEGES;
3. 确定配置参数
提前明确以下参数,后续脚本中会用到:
| 参数名 | 说明 | 示例值 |
|---|---|---|
| 日志保留天数 | 超过该天数的日志会被清理 | 7 |
| 备份存储路径 | 二进制日志备份存放的目录 | /data/mysql/binlog_backup |
| MySQL连接信息 | 管理用户的连接参数 | -h localhost -u binlog_admin -pyour_password |
完整管理脚本示例
以下是一个可直接使用的Shell脚本示例,包含日志备份、过期清理、状态检查三个核心功能:
#!/bin/bash
# 基础配置参数
MYSQL_CMD="/usr/local/mysql/bin/mysql -h localhost -u binlog_admin -pyour_password"
BINLOG_BACKUP_DIR="/data/mysql/binlog_backup"
RETENTION_DAYS=7
LOG_FILE="/var/log/mysql_binlog_manage.log"
# 记录日志函数
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> $LOG_FILE
}
# 检查备份目录是否存在
if [ ! -d "$BINLOG_BACKUP_DIR" ]; then
mkdir -p $BINLOG_BACKUP_DIR
log "创建备份目录 $BINLOG_BACKUP_DIR"
fi
# 1. 备份当前所有二进制日志
log "开始备份二进制日志"
$BINSQL_CMD="/usr/local/mysql/bin/mysqlbinlog"
$BINSQL_CMD --read-from-remote-server --host=localhost --user=binlog_admin --password=your_password --raw --result-file=$BINLOG_BACKUP_DIR/ $(mysql -h localhost -u binlog_admin -pyour_password -e "SHOW BINARY LOGS" | awk 'NR>1 {print $1}')
if [ $? -eq 0 ]; then
log "二进制日志备份完成"
else
log "二进制日志备份失败"
exit 1
fi
# 2. 清理超过保留天数的二进制日志
log "开始清理过期二进制日志"
# 计算过期时间对应的日志位置
EXPIRE_LOG=$($MYSQL_CMD -e "SHOW BINARY LOGS" | awk -v days=$RETENTION_DAYS 'NR>1 {if (systime() - mktime(substr($2,1,4)" "substr($2,6,2)" "substr($2,9,2)" 00 00 00") > days*86400) print $1}' | tail -1)
if [ -n "$EXPIRE_LOG" ]; then
$MYSQL_CMD -e "PURGE BINARY LOGS TO '$EXPIRE_LOG'"
if [ $? -eq 0 ]; then
log "已清理 $EXPIRE_LOG 之前的所有二进制日志"
else
log "清理过期日志失败"
fi
else
log "没有需要清理的过期二进制日志"
fi
# 3. 检查二进制日志状态
log "开始检查二进制日志状态"
$BINLOG_STATUS=$($MYSQL_CMD -e "SHOW BINARY LOGS" | awk 'NR>1 {sum+=$3; count++} END {print "总日志数:"count", 总大小:"sum"字节"}')
log "当前二进制日志状态: $BINLOG_STATUS"
# 检查磁盘占用是否超过阈值(比如10G)
$BINLOG_SIZE=$($MYSQL_CMD -e "SHOW BINARY LOGS" | awk 'NR>1 {sum+=$3} END {print sum}')
if [ $BINLOG_SIZE -gt 10737418240 ]; then
log "警告:二进制日志总大小超过10G,请及时检查"
fi
log "本次二进制日志管理操作完成"脚本使用注意事项
使用上述脚本时需要注意以下几点:
- 首次运行前先手动测试PURGE命令,确认不会误删正在使用的日志,避免影响主从复制
- 建议将脚本加入crontab定时执行,比如每天凌晨2点执行:
0 2 * * * /path/to/binlog_manage.sh - 定期查看日志文件/var/log/mysql_binlog_manage.log,确认脚本执行状态
- 如果数据库开启了GTID模式,清理日志时需要额外校验GTID相关信息,避免删除未同步到从库的日志
常见问题排查
如果脚本执行出现异常,可以从以下几个方面排查:
- 权限问题:检查管理用户是否有足够的权限执行SHOW BINARY LOGS和PURGE命令
- 路径问题:确认mysql、mysqlbinlog命令路径正确,备份目录有写入权限
- 密码问题:如果密码包含特殊字符,需要在脚本中进行转义,或者使用配置文件存储连接信息
- 主从复制问题:如果是主库,清理日志前确认所有从库都已经同步完对应日志,避免复制中断