1.背景

某个项目为了实现通过CanalMySql自动同步至Redis的目的,开启了MySqllog-bin模式(binary-log,二进制日志)。开启方式很简单,这里只是给出初步介绍:

//关闭MySql服务

//vi /etc/my.cnf

[mysqld]
...
log-bin=mysql-bin
...

//开启MySql服务

开启了二进制日志后,我们确实实现了Redis的自动同步。但是后来发现服务器磁盘空间暴减,通过分析发现是MySql产生了大量二进制文件,如下:

[root@localhost mysql]# ls -1
ibdata1
ib_logfile0
ib_logfile1
ib_logfile0
mysql-bin.000001
mysql-bin.000002
mysql-bin.000003
mysql-bin.000004
...
mysql-bin.index
...

我分配给MySql的磁盘空间只有20G,经常会一两天就产生MySql磁盘爆满导致MySql服务不可用的问题。
然后我就开始了悲催的MySql日志清理之旅。

2.第一种策略:手动清理

刚开始都是通过手动进行清理。
通常这么做:

#将指定时间之前的日志清理
purge binary logs before '2018-02-01 12:00:00';

#将指定日志文件之前的日志清除
purge binary logs to 'mysql-bin.000003';

这么做一直都能达到清理的目的,就是过几天就需要清理一次,很是繁琐。
但是因为工期紧,任务重,我也没花时间了解别的方式,直到有一天…

有一天,开启了MySql的主从模式,然后照例通过purge进行日志清理。
刚开始也是没有问题的,然后,有一次执行了purge之后就没有然后了:MySql直接被玩坏了…

后来分析,应该是我们清理日志的时刻,正巧与主从复制冲突了,然后就出错了。
冲突的原因我没有深究,但是大概有可能如下:

  • 恰巧试图清除正在被从服务器读取的日志,清除失败
  • 恰巧清除了从服务器想要读取的日志,清除成功,但是从服务器不能再复制

最后,经过一番研究,通过flush logs + restart解决了问题。

3.第二种策略:自动清理

考虑到purge的不稳定性以及天天清理日志的烦恼,后来采取了自动清理策略。实现方法如下:

一次性的(不推荐:因为服务重启,配置失效):

SQL > set global expire_logs_days = 3;

一劳永逸(就是改配置,推荐):

//关闭MySql服务

//vi /etc/my.cnf
[mysqld]
...
#开启binary log
log-bin=mysql-bin

#日志超过3天自动过期
expire_logs_days = 3
...

//开启MySql服务