第一次接触MySQL的binlog文件是在2013年维护一个电商系统时。当时凌晨3点收到磁盘空间报警,发现是binlog文件占用了近200GB空间。这个经历让我深刻认识到,DBA必须掌握binlog的清理方法。
binlog(二进制日志)是MySQL最重要的日志之一,它以事件形式记录所有更改数据的SQL语句。主要作用包括:
在默认配置下,MySQL不会自动清理binlog文件,这会导致两个典型问题:
这是官方推荐的标准方法,语法如下:
sql复制PURGE BINARY LOGS TO 'mysql-bin.000010';
PURGE BINARY LOGS BEFORE '2023-06-01 00:00:00';
第一种方式会删除指定文件名之前的所有binlog(保留mysql-bin.000010及之后的文件)。我在生产环境更推荐使用时间点删除,因为:
重要提示:执行前务必确认从库已经读取了要删除的binlog,否则会导致主从复制中断。可以通过
SHOW SLAVE STATUS查看从库当前的读取位置。
在my.cnf配置文件中添加:
code复制[mysqld]
expire_logs_days = 7
这个参数表示binlog的过期天数(默认0表示永不过期)。设置后:
实测建议:
max_binlog_size控制单个文件大小(默认1GB)在MySQL停止服务的情况下,可以直接删除/var/lib/mysql/目录下的mysql-bin.000*文件。但这种方法存在严重风险:
仅在以下极端场景考虑使用:
我设计的自动化方案包含三个组件:
bash复制#!/bin/bash
DISK_USAGE=$(df -h / | awk 'NR==2 {print $5}' | tr -d '%')
if [ $DISK_USAGE -gt 85 ]; then
mysql -e "PURGE BINARY LOGS BEFORE DATE_SUB(NOW(), INTERVAL 3 DAY)"
fi
sql复制-- 保留7天binlog
SET @keep_days = 7;
SET @purge_time = DATE_FORMAT(DATE_SUB(NOW(), INTERVAL @keep_days DAY), '%Y-%m-%d 00:00:00');
PURGE BINARY LOGS BEFORE @purge_time;
bash复制mysqldump --master-data=2 | gzip > backup_$(date +%F).sql.gz
if [ $? -eq 0 ]; then
mysql -e "PURGE BINARY LOGS BEFORE DATE_SUB(NOW(), INTERVAL 2 DAY)"
fi
在主从复制环境中,必须遵守以下原则:
SHOW SLAVE STATUS确认Relay_Master_Log_Filesync_binlog=1确保binlog写入安全典型问题处理:
清理binlog可能带来的影响:
如果误删了正在使用的binlog,按以下步骤处理:
CHANGE MASTER TO重新指定复制起点有时删除文件后df显示空间未释放,可能原因:
bash复制lsof | grep deleted | grep mysql-bin
sql复制FLUSH LOGS;
bash复制sync
GTID模式下的清理:
sql复制-- 查看已执行的GTID集合
SELECT @@global.gtid_executed;
-- 安全清理
PURGE BINARY LOGS BEFORE '2023-06-01';
组复制(MGR)环境:
group_replication_set_as_primary切换后清理完善的binlog管理应该包含:
空间监控(每日检查)
sql复制SELECT
SUM(size)/1024/1024 AS total_size_mb,
COUNT(*) AS file_count
FROM mysql.slave_master_info;
生命周期管理
报警阈值设置
最后分享一个实用技巧:在清理前先执行FLUSH BINARY LOGS创建新日志文件,这样可以确保正在使用的日志不会被立即删除,给从库留出同步时间窗口。