1. 故障描述

一个服务接口突然报数据库连接异常,错误信息如下:

2022-12-30-15-10 [qtp503642634-1677050] [com.itcoder.services.SignService] [ERROR] - checkCertAuthority:nested exception is org.apache.ibatis.exceptions.PersistenceException: 
### Error querying database.  Cause: org.springframework.jdbc.CannotGetJdbcConnectionException: Failed to obtain JDBC Connection; nested exception is java.sql.SQLTransientConnectionException: HikariPool-1 - Connection is not available, request timed out after 30000ms.
### The error may exist in class path resource [mybatis/TbAppMapper.xml]
### The error may involve com.itcoder.dao.ITbAppDAO.selectByPrimaryKey
### The error occurred while executing a query
### Cause: org.springframework.jdbc.CannotGetJdbcConnectionException: Failed to obtain JDBC Connection; nested exception is java.sql.SQLTransientConnectionException: HikariPool-1 - Connection is not available, request timed out after 30000ms.

去检查了下数据库,发现数据库磁盘空间率用率100%了,MySQL数据目录下全是binlog日志文件,有900多个!

2. 解决办法

第一步:手动清理binlog日志

清除30天之前的binlog日志:

mysql> PURGE BINARY LOGS BEFORE (date(now()) + interval 0 second - interval 30 day);

第二步:设置binlog过期时间

第一步只是临时解决当前问题,还需要设置binlog日志过期时间,MySQL会自动清除过期binlog日志文件:

mysql> SET GLOBAL expire_logs_days=30;

以上配置会在重启MySQL后失效,因此还需要修改my.cnf文件,在[mysqld]模块下加入如下配置:

[mysqld]
......
expire_logs_days=30

设置之后不会立即清除,触发条件是:

  1. binlog文件大小超过max_binlog_size(默认1G)发生日志文件轮询时
  2. 手动执行flush logs
  3. 重新启动时(MySQL将会生成一个新文件用于记录binlog)

--- 题外话 ---

由于这台MySQL数据库是测试服务器,所以没对该服务器资源使用情况进行监控,没能在资源即将不足时触发预警,最终导致这起“惨案”的发生。

所以,监控很重要!