早上打开监控,发现某个核心业务表突然报错“The table is read only”,心里咯噔一下。这种问题在MySQL运维里不算罕见,但每次碰上,都够让人头疼一阵子。数据库表变只读,意味着业务在写入环节直接卡死,用户下单失败、日志写不进去、状态更新不了,影响面往往不小。

很多朋友第一反应是“权限被改了”,然后就急着去翻授权表。其实,MySQL表变只读的原因有好几类,权限只是其中之一,而且往往不是最常触发的。我见过不少情况,是磁盘满了、文件系统只读、或者复制架构里从库设置了。所以,遇到这问题别慌,按下面三步来排查,多数情况能快速定位并恢复。
第一步:先看磁盘和文件系统状态,这一步最容易被忽略
有次帮一个客户处理问题,业务反馈所有表都变成只读了,查了半天权限没问题,发现是服务器根分区满了。MySQL在写入时如果发现磁盘空间不足,会进入保护模式,把表标记为只读,防止数据文件写坏。这种设计挺聪明,但遇到时很容易让人误判。
排查命令很简单: 看看各分区使用率,尤其留意数据目录所在分区。如果已经达到100%,清理下日志、临时文件、或者旧的binlog,释放空间后,表通常会自动恢复可写。另外, 命令看看数据目录所在的文件系统是不是被重新挂载成了只读。有时候系统异常重启,或者云盘出现元数据错误,文件系统会自动切换成ro模式,这种情况得先修复文件系统,再重新挂载为rw,表才能恢复。
第二步:检查MySQL的只读参数,别被全局设置坑了
如果磁盘和文件系统都没问题,那就得看MySQL自身的参数了。 和 这两个变量是主要嫌疑对象。在从库架构里,运维人员经常把从库设置成 ,防止有人手滑写入数据; 更严格,连超级权限账号也禁止写入。
排查方法:执行 看看当前值。如果是从库,且业务确实不需要在从库写入,那保持只读是正常的;但如果主库出现了 ,多半是之前有人改过配置,或者配置文件里写了没注释掉。直接执行 和 就能临时解除,但注意,如果不改配置文件,重启后还是会变回去。
还有一种情况比较隐蔽——在MySQL 5.7及以上版本,如果开启了,那整个InnoDB引擎都是只读的,这个参数通常只在特殊场景下用,比如数据迁移或只读分析实例。平时遇到表只读,这个参数基本可以排除,但也值得看一眼。
第三步:深入表级别,检查权限和锁定状态
前两步都没问题的话,就得把焦点放到具体表上了。先查 看看是不是对这个表只有SELECT权限,没有INSERT、UPDATE、DELETE。权限问题在开发环境挺常见,尤其是有人用数据字典工具导表时,不小心把权限覆盖了。
另外,表被LOCK TABLES READ锁定也会表现为只读。执行 看看有没有表处于锁定状态。如果有,找到持有锁的会话,用 命令终止它,或者等它释放锁。还有一点,MySQL 8.0里引入了,这个全局备份锁也会让所有表变成只读,如果有人在跑备份,业务写入就会报错。
排查完这三步,绝大多数情况都能定位到原因。但有些时候,问题比较顽固,比如数据文件损坏导致表被标记为只读,这时候就得用 检查一下表状态,必要时用 修复。不过,这两种操作建议在低峰期做,毕竟会占资源。
恢复读写权限只是第一步,后续得想想怎么避免再犯。如果是磁盘满导致的,建议给磁盘使用率加个监控,到80%就告警,别等到写不进去了才处理。如果是参数被误改,检查一下配置管理流程,是不是有人手动改过在线参数没同步到配置文件。如果是权限问题,建议定期审计授权表,别让权限越积越乱。
还有个容易踩的坑——某些云数据库服务(比如RDS)有自己的一套只读策略,比如主备切换时,旧主库会被自动置为只读,防止脑裂。这时候你在控制台改参数是没用的,得在服务商的控制面板里重新设置实例角色。所以,用云数据库的朋友,遇到表只读,先看下实例状态是不是发生了切换。
表变只读这事儿,说大不大,说小不小。处理得快,几分钟就能恢复业务;处理得慢,可能影响一大片。关键还是别慌,按“磁盘文件系统—全局参数—表级权限”这个顺序来,基本不会跑偏。干运维这行,遇事多留个心眼,把每一步的原因记下来,下次再碰到同类问题,直接就能对症下药了。
提醒一句,修复完记得验证一下写入是否真的恢复了。最简单的方式,在业务表里UPDATE一条记录,或者INSERT一条测试数据,然后回滚。别只看参数变了就以为万事大吉,实际写入成功才是真的恢复。MySQL这工具,平时看着温顺,真出问题的时候,细节决定成败。


