一次服务器告警的处理

今天客户在群里一阵@我,说是收到服务器告警短信了。

Usage disk is more than 90% on volume /home...

磁盘空间告急啊。

分析

这台机器上部署了应用和MySQL,日志文件和数据库文件应该是存储的大头,所以立即锁定目标。

为了不泄漏公司机密,以下数据都是我本地的,有内味就行了

我迅速连上公司vpn,ssh到目标主机。

test@Evil:~$ df -h
Filesystem Size Used Avail Use% Mounted on
rootfs 59G 51G 7.7G 87% /
none 59G 51G 7.7G 87% /dev
none 59G 55G 7.7G 92% /home
...

可以看到​​/home​​目录果然超过90%。

test@Evil:~$ du -h -d 1 *
37G Mysql
12G logs/xxx
12G logs
...

查看/home目录下文件的大小,可以看到确实是Mysql和logs占了使用空间的大头。。

清理应用日志

日志文件好整,我获得了客户的授权,一波删除带走

rm -rf logs/xxx/xx-2019-*.log

去年的日志一波带走

test@Evil:~$ du -h -d 1 *
37G Mysql
2G logs/xxx
2G logs
...

看到回了口血,一阵欣慰,毕竟在生产​​rm -rf​​的机会不多。。

mysql binlog

接下来就是搞Mysql了

我知道,它占用空间的大头,也就是数据库文件和binlog文件了,binlog好搞,先易后难。

因为是单点的mysql,所以不用担心什么主备同步问题,带走。。

mysql> reset master; # 清空所有 binlog 文件

mysql ibdata1

mysql的数据文件,我真的是头疼,上次处理相似问题的时候,跟公司的dba讨论了一下,好像是得先导出数据,然后删除ibdata1文件,再启动mysql,导入数据。

大白天的怎么能干这种事儿呢?

只能先分析一波了。



ibdata1是啥呢?
ibdata1是一个用来构建innodb系统表空间的文件,这个文件包含了innodb表的元数据、撤销记录、修改buffer和双写buffer。如果file-per-table选项打开的话,该文件则不一定包含所有表的数据。当innodb_file_per_table选项打开的话,新创建表的数据和索引则不会存在系统表空间中,而是存放在各自表的.ibd文件中。显然这个文件会越来越大,innodb_autoextend_increment选项则指定了该文件每次自动增长的步进,默认是8M.



他为啥会变大?
ibdata1存放数据,索引和缓存等,是MYSQL的最主要的数据。所以随着数据库越来越大,表也会越大,这个无法避免的。



怎么搞掉它?
首先我们把数据库备份下来,然后直接删除ibdata文件(为了保险起见最好先全备一次,做到数据安全和完整),然后再重新导入数据库文件即可!



#停止业务,备份一次全库
mysqldump -u root -p password --all-databases > all_mysql.sql
#备份完成,停止数据库
systemctl stop mariadb 或者 service mysqld stop
#修改配置文件
#在[mysqld]下增加下面配置 innodb_file_per_table=1

#可以重启mysql后
service mysqld restart
#验证
mysql -u root -p password

show variables like '%per_table%';

+-----------------------+-------+
| Variable_name | Value | |
+-----------------------+-------+
| innodb_file_per_table | ON |
+-----------------------+-------+

1 row in set (0.00 sec)

innodb_file_per_table的状态变为ON

5、删除ibdata1文件和日志

rm -rf ibdata1
rm -rf ib_logfile*

6、恢复数据
mysql -u user -p password
source all_mysql.sql

在MySQL的配置文件[mysqld]部分,增加innodb_file_per_table参数。可以修改InnoDB为独立表空间模式,每个数据库的每个表都会生成一个数据空间。

优点:


  • 每个表都有自已独立的表空间。
  • 每个表的数据和索引都会存在自已的表空间中。
  • 可以实现单表在不同的数据库中移动。
  • 空间可以回收(除drop table操作处,表空不能自已回收)

    • Drop table操作自动回收表空间,如果对于统计分析或是日值表,删除大量数据后可以通过​​alter table TableName engine=innodb;​​回缩不用的空间。
    • 对于使innodb-plugin的Innodb使用turncate table也会使空间收缩。
    • 对于使用独立表空间的表,不管怎么删除,表空间的碎片不会太严重的影响性能,而且还有机会处理。


缺点:

  • 单表增加过大,如超过100个G。

总结

ibdata得等晚上搞了,但愿顺利。

不过这台机器的问题,这么搞也不是长久之际。数据库这块,之前会存日志到库表里,后来客户觉得有日志文件就不用了,写日志到文件的代码已经被我注释了。今晚搞一波ibdata,应该以后增速不会很快了。应用日志一天几百兆,这块得做个定时任务,定期删除日志文件,等下写个脚本,加到系统的crontab里。这样应该能消停了。