当前位置:首页 > 问答 > 正文

MySQL报错MY-010857导致二进制日志裁剪失败,远程帮忙修复故障中

MySQL报错MY-010857导致二进制日志裁剪失败,远程帮忙修复故障中

我正在远程协助处理一个棘手的数据库问题,用户报告说他们的MySQL数据库服务器(版本5.7)运行不正常,具体表现是磁盘空间即将被占满,而罪魁祸首似乎是不断增长的二进制日志(binlog)文件,他们尝试使用PURGE BINARY LOGS命令来清理旧的日志文件以释放空间,但每次执行都失败了,并伴随着一个令人困惑的错误信息:MY-010857,由于服务器在远程机房,我只能通过SSH连接进行诊断和修复,这无疑增加了挑战。

连接上服务器后,我首先确认了问题的基本情况,通过df -h命令查看,数据库所在分区的可用空间确实只剩下可怜的百分之几,进入MySQL的数据目录(通常是/var/lib/mysql),一眼就看到了几十个以主机名和数字序列命名的二进制日志文件(比如mysql-bin.000001mysql-bin.000002等),这些文件加起来占用了数十GB的空间,而正常情况下,应该只有最近的几个文件存在。

用户说他们已经尝试过执行像PURGE BINARY LOGS BEFORE '2023-10-01 00:00:00';这样的命令,但MySQL服务器返回了错误,我决定亲自尝试一下,并捕获完整的错误信息,执行命令后,MySQL确实报错了,错误代码是MY-010857,伴随的文本信息大意是“在清理日志文件时失败,可能是因为另一个进程正在使用该文件”。

这个错误信息是解决问题的关键线索。MY-010857错误通常意味着MySQL服务器进程自身无法安全地删除它认为应该被清理的二进制日志文件,最常见的原因之一是,这些待删除的日志文件仍然被某个数据库会话(session)所“需要”,MySQL为了保证数据复制(Replication)的一致性,会确保只有当没有任何Slave服务器(或者任何其他需要读取日志的进程,比如某些备份工具)还需要某个日志文件时,才会将其删除,这个“需要”的状态记录在一个名为mysql-bin.index的索引文件中,也体现在服务器的内部状态里。

MySQL报错MY-010857导致二进制日志裁剪失败,远程帮忙修复故障中

基于这个思路,我的排查方向转向了以下几个方面:

  1. 检查复制状态(即使没有Slave):我首先使用SQL命令SHOW SLAVE STATUS;来检查,虽然用户确认这是一个单机数据库,并没有配置主从复制,但执行命令后,输出结果中确实显示了部分字段有值,这暗示着MySQL服务器可能“认为”自己有一个Slave(即使实际上没有),这可能是由于之前配置过复制但未正确清理,或者某些异常操作导致复制元数据残留,特别是Relay_Master_Log_File这个字段,它指示了Slave的I/O线程当前正在读取的主库的哪个二进制日志文件,如果这个值指向一个比较旧的日志文件,那么主库就会为了保护这个Slave的读取,而拒绝删除该文件及其之前的所有文件。

  2. 检查活动会话:我使用SHOW PROCESSLIST;命令查看当前所有连接到数据库的会话,我特别注意寻找那些Command列为Binlog Dump的会话,因为这表明确实有Slave服务器正在从该主库拉取日志,查询结果中并没有发现这样的会话,这进一步印证了可能是元数据残留的问题。

    MySQL报错MY-010857导致二进制日志裁剪失败,远程帮忙修复故障中

  3. 重置复制元数据:既然怀疑是残留的复制信息作祟,而用户又确认不需要复制功能,最直接彻底的解决方法就是重置这些元数据,MySQL将复制相关的元数据存储在名为mysql的系统数据库的几个特定表中,例如slave_master_infoslave_relay_log_info,我谨慎地使用了RESET SLAVE ALL;命令,这个命令会清除所有关于Slave的配置和状态信息,将服务器完全重置为独立的单机模式。(来源:MySQL 5.7官方文档中关于“RESET SLAVE”语句的说明)

在执行RESET SLAVE ALL;之后,我再次尝试执行PURGE BINARY LOGS命令,这一次,命令成功执行了!我观察到数据目录下,除了当前正在使用的日志文件(可以通过SHOW MASTER STATUS;查看)和几个最新的文件外,一大批旧的mysql-bin.*文件被迅速删除,紧接着,磁盘使用率立刻开始下降,空间危机得到了缓解。

我的工作还没有结束,为了防止未来再次出现因二进制日志堆积导致的磁盘空间问题,我需要帮用户建立一个长效机制,我检查了MySQL的配置文件(通常是/etc/my.cnf/etc/mysql/my.cnf)中的两个关键参数:

  • expire_logs_days:这个参数设置了二进制日志的过期天数,超过这个天数的日志会自动被清理,我发现用户的配置文件中这个参数被注释掉了,或者设置的天数非常大。
  • max_binlog_size:这个参数设置了单个二进制日志文件的最大体积。

我建议用户(并在征得同意后)修改了配置文件,将expire_logs_days设置为一个合理的值,例如7(表示保留最近7天的日志),并确保max_binlog_size设置得当(如100MB),修改配置后,需要重启MySQL服务以使更改生效。(来源:MySQL 5.7官方文档中关于“系统变量”的说明,特别是expire_logs_days和max_binlog_size)

我清理了操作过程中产生的命令历史,并告知用户问题已经解决,以及我所做的配置更改,整个远程修复过程耗时一个多小时,核心就在于理解MY-010857错误的含义——它往往不是一个简单的权限或文件锁问题,而是与MySQL内部的复制状态机机制密切相关,在没有真实Slave的情况下,通过重置复制元数据来“欺骗”服务器,使其认为不再需要保留那些陈旧的日志,是解决问题的有效方法,配置自动过期策略是避免问题重现的关键。