记一次服务器磁盘报警;原因:Mysql binlog日志太多了;及解决方法。

中午的时候突然收到服务器发的警告,看见我的磁盘使用率已经百分之九十多了,还以为给攻击了或者给docker占满了。

进入后台才发现不是,一看全是 Mysql 的日志给占满了。

微信图片编辑_20230329183102微信截图_20230329184255

解决过程:

一、查找占用大的文件

使用 du 命令可以查找占用内存大的文件,如果不确定哪个目录占用内存大的可以先从根目录一层一层的查找

1
du -sh *

这里我找到的就是 Mysql 的日志文件,可以看见,日志文件已经占用我6G多的空间了,难怪会报警。

猜想:其他程序问题,一直读写数据库,导致数据库产生了大量的binlog日志,把磁盘空间占满了

微信截图_20230329184918

二、删除文件

找到了这些大文件,发现是数据的日志文件,那就直接进入数据库删除吧

1
2
# 进入数据库
mysql -u root -p

mysql 日志的种类,一般来说,日志有五种,分别为:

  • 错误日志:-log-err (记录启动,运行,停止mysql时出现的信息)

  • 二进制日志:-log-bin (记录所有更改数据的语句,还用于复制,恢复数据库用)

  • 查询日志:-log (记录建立的客户端连接和执行的语句)

  • 慢查询日志: -log-slow-queries (记录所有执行超过long_query_time秒的所有查询)

  • 更新日志: -log-update (二进制日志已经代替了老的更新日志,更新日志在MySQL 5.1中不再使用)

查看这些日志:

1
2
3
4
5
6
7
8
9
10
11
12
13
mysql> show master logs;
+------------------+------------+
| Log_name | File_size |
+------------------+------------+
| mysql-bin.000008 | 1073748974 |
| mysql-bin.000009 | 1073744692 |
| mysql-bin.000010 | 1073742182 |
| mysql-bin.000011 | 1073743863 |
| mysql-bin.000012 | 1073746062 |
| mysql-bin.000013 | 1073748330 |
| mysql-bin.000014 | 399853232 |
+------------------+------------+
7 rows in set (0.00 sec)

查看正在使用的日志文件:

1
2
3
4
5
6
7
mysql> show master status;
+------------------+-----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+-----------+--------------+------------------+-------------------+
| mysql-bin.000014 | 420566379 | | | |
+------------------+-----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

当前正在使用的日志文件是 mysql-bin.000014 ,那么删除日志文件的时候应该排除掉该文件。

1
2
# 查看指定binlog文件的内容 
show binlog events in 'mysql-bin.000015'

rm 删除的时候,一定不能删除正在使用的 binlog 文件。另外用rm 删除的 binlog ,一定要再purge一次,不然数据库无法启动。

1
2
3
4
5
6
7
# 删除日志文件的命令:purge binary logs to ‘mysql-bin.xxxxxxx’;

# 删除除 mysql-bin.000014 以外的日志文件
purge binary logs to 'mysql-bin.000014';

# 一下干净多了:空间也释放了。
# 它又绿回来了。

微信截图_20230330000648

三、mysql 定时清理日志文件

如果每次等到发现空间不足的时候才去手动删除日志文件,这种方式太麻烦了。

那么,我们就需要设置mysql,让它能自动清理日志文件。

编辑mysql的配置文件,设置expire_logs_days(mysql定时删除日志文件)

1
vim /etc/my.cnf

在my.cnf中,添加或修改 expire_logs_days 的值 (这里设置的自动删除时间为10天, 默认为0不自动删除)

1
expire_logs_days=10

修改后,重启 mysql 就会生效。

但是,在生产环境中,重启mysql数据库往往会付出很高的代价。

于是,可以在不重启 mysql 的情况下,修改expire_logs_days值

登陆到mysql,并输入一下命令。 如下:

1
2
3
mysql> show variables like '%log%';

mysql> set global expire_logs_days = 10;

设置完后,可以通过 show variables like ‘%log%’; 看到expire_logs_days的值已被修改成10。

注意:通过这种方式设置expire_logs_days虽然不需要重启mysql即可生效,但是该方式在重启mysql之后,值会被恢复。

于是,建议通过mysql命令设置expire_logs_days的同时,也修改/etc/my.cnf下的expire_logs_days=10配置,这样在下次重启mysql的时候,expire_logs_day s也一样是10;

这是数据库的操作日志,例如UPDATE一个表,或者DELETE一些数据,即使该语句没有匹配的数据,这个命令也会存储到日志文件中,还包括每个语句执行的时间,也会记录进去的。

这样做主要有以下两个目的:
1:数据恢复
如果你的数据库出问题了,而你之前有过备份,那么可以看日志文件,找出是哪个命令导致你的数据库出问题了,想办法挽回损失。
2:主从服务器之间同步数据
主服务器上所有的操作都在记录日志中,从服务器可以根据该日志来进行,以确保两个同步。

处理方法分两种情况:
1:只有一个 mysql 服务器,那么可以简单的注释掉这个选项就行了。
vi /etc/my.cnf 把里面的log-bin这一行注释掉,重启 mysql 服务即可。
2:如果你的环境是主从服务器,那么就需要做以下操作了。
A:在每个从属服务器上,使用SHOW SLAVE STATUS来检查它正在读取哪个日志。
B:使用SHOW MASTER LOGS获得主服务器上的一系列日志。
C:在所有的从属服务器中判定最早的日志,这个是目标日志,如果所有的从属服务器是更新的,就是清单上的最后一个日志。
D:清理所有的日志,但是不包括目标日志,因为从服务器还要跟它同步。