MySQL超级只读模式下读写错误导致无法操作,远程协助修复方案分享
- 问答
- 2025-12-29 17:37:36
- 6
前段时间,我们遇到了一个非常棘手的问题,一台非常重要的MySQL数据库服务器,突然之间变得几乎“砖化”了,任何试图对数据库进行更改的操作,比如更新一个用户信息、插入一条新的订单记录,甚至是创建一个简单的临时表,都会立刻弹出一个错误提示,大概意思是说“MySQL服务器正处于只读模式,无法执行写操作”。
但奇怪的是,我们的程序并没有主动去设置这个只读模式,更麻烦的是,这台服务器是放在远端的机房里的,我们只能通过远程连接来访问和操作,无法直接接触到物理机器,这就排除了直接去机房重启服务器这种最简单粗暴的解决方法,情况变得很紧急,因为业务系统几乎停摆,所有需要写入数据库的功能都失效了。
我们尝试了最直接的思路:既然是被设置成了只读模式,那肯定有办法把它取消掉,我们使用具有最高权限的root账户登录到MySQL数据库,然后执行了那个看起来应该能解决问题的命令:SET GLOBAL read_only = OFF;,这个命令的意思是告诉MySQL,取消全局的只读设置。
执行之后,系统返回了“Query OK”,看起来是成功了,我们满怀希望地立刻尝试执行一条简单的UPDATE语句来测试,结果令人沮丧,那个熟悉的只读错误提示又出现了,写入操作依然被禁止,这说明有更深层次的原因在维持着只读状态,简单地设置read_only参数无效。
第一次尝试失败后,我们开始扩大排查范围,根据MySQL的官方文档和一些技术社区的资料(比如MySQL官方手册和Percona博客的相关讨论),我们了解到,在MySQL中,还有一个比read_only更高级、更严格的参数,叫做super_read_only,当super_read_only被开启时,它不仅会激活普通的只读模式,还会限制即使是具有SUPER权限的用户也无法进行写操作,这就像是一把更坚固的锁。
我们立刻检查了这个参数的状态,执行命令:SHOW VARIABLES LIKE 'super_read_only';,果不其然,它的值是ON,也就是开启状态,这下就解释了为什么刚才用root用户取消read_only失败了,因为“超级只读”模式压制了我们的操作。
找到了根源,我们再次尝试用root权限执行命令:SET GLOBAL super_read_only = OFF;,心想这次总该行了吧,现实又给了我们一击——命令执行失败了!系统提示我们没有足够的权限去修改这个变量,这简直不可思议,因为使用的是最高权限的root账户,理论上应该无所不能才对,我们意识到问题可能不在MySQL内部,而是出在更底层的外部环境。
团队里的一位资深工程师提出了一个关键猜想:会不会是服务器操作系统层面的磁盘空间满了?因为根据他的经验,当数据库所在的磁盘分区被写满,没有剩余空间时,MySQL作为一种保护机制,会自动进入一种严格的只读状态,以防止数据文件损坏,这种状态可能比手动设置的super_read_only更难解除,因为根源是硬件资源问题。
我们立刻通过远程SSH连接登录到数据库服务器本身的操作系统,使用df -h命令查看磁盘使用情况,结果发现,存放MySQL数据文件的那个分区,使用率果然是100%,已经完全被占满了,真相大白!磁盘满导致了MySQL的自保护机制触发,自动开启了超级只读模式,而且在这种状态下,由于没有磁盘空间可供操作,我们甚至连关闭只读模式的命令都无法成功执行,因为MySQL需要写入一些状态信息。
接下来的任务就很明确了:清理磁盘空间,我们开始排查是什么文件占用了如此巨大的空间,首先使用du -sh命令逐层排查大目录,最终发现,是MySQL的二进制日志文件(binlog)体积异常庞大,达到了几十个G,把空间彻底撑满了,这些日志文件本来是用于数据复制和恢复的,但由于配置问题,没有设置自动清理策略,导致它们无限堆积。
我们立即采取了行动:
- 手动删除了大量已经过期的、不再需要的早期binlog文件,注意,删除时使用的是MySQL的命令
PURGE BINARY LOGS BEFORE ...,而不是直接在操作系统里rm删除,以确保数据一致性。 - 删掉一部分文件后,磁盘有了剩余空间,我们抱着试一试的心态,再次登录MySQL,发现已经可以成功执行
SET GLOBAL super_read_only = OFF;命令了,执行成功后,紧接着再执行SET GLOBAL read_only = OFF;。 - 为了验证修复是否成功,我们马上执行了一条测试用的UPDATE语句,这次,命令成功执行,没有再报错!数据库的写入功能恢复了。
问题虽然解决了,但为了防止未来再次发生,我们做了后续加固:
- 立即修改了MySQL的配置文件(my.cnf),明确设置了
expire_logs_days参数,让MySQL自动清理超过指定天数的binlog文件。 - 增加了对服务器磁盘空间的监控告警,一旦使用率超过85%,就会立即发送通知给运维人员。
- 制定了定期检查数据库日志文件和磁盘空间的流程。
回顾这次远程协助修复经历,核心教训是:当数据库出现无法写入的只读错误时,不能仅仅盯着MySQL内部的read_only参数,必须由浅入深地进行排查,顺序应该是:先检查MySQL的参数状态(read_only和super_read_only),如果无法简单修改,一定要立刻检查服务器操作系统的资源情况,特别是磁盘空间,很多时候,问题的根源往往在数据库之外,这次通过层层排查,最终找到磁盘空间这个“罪魁祸首”,才成功解决了问题。

本文由黎家于2025-12-29发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:http://www.haoid.cn/wenda/70781.html
