必须先修复文件系统,否则任何set global read_only=off或修改my.cnf都无效;确认是否文件系统只读:运行mount | grep "/var/lib/mysql"看是否含ro,touch测试写入,dmesg查ext4/xfs错误,修复后清除socket/pid文件再重启mysql。

MySQL InnoDB 因文件系统报错进入只读状态,不是数据库配置问题,而是底层存储已拒绝写入——必须先修复文件系统,否则任何 SET GLOBAL read_only = OFF 或修改 my.cnf 都无效。
确认是不是文件系统只读(而非 MySQL 自身只读)
很多人一看到 ERROR 1290 (HY000): The MySQL server is running with the --read-only option 就去改 read_only,但真正原因可能是磁盘挂载为只读。直接验证:
- 运行
mount | grep "/var/lib/mysql"(路径按实际数据目录调整),如果输出含ro(read-only),说明文件系统已被内核强制只读 - 尝试创建测试文件:
touch /var/lib/mysql/test.tmp,若报Read-only file system,100% 是文件系统层面问题 -
SHOW VARIABLES LIKE 'read_only';和SHOW VARIABLES LIKE 'super_read_only';此时可能仍显示OFF,但这只是表象——InnoDB 在 open table 时会检测底层 write 权限,失败后自动置为只读模式并静默记录到 error log
检查并修复文件系统错误
文件系统报错(如 ext4 的 journal 错误、XFS 的 AG corruption)常导致内核 remount 为 ro。不要跳过这步直接重启:
- 先查日志定位根源:
dmesg -T | grep -i "ext4\|xfs\|error\|readonly",重点关注类似EXT4-fs error (device sda1)或XFS: failed to initialize the log的条目 - 确认文件系统类型:
df -T /var/lib/mysql - 如果是 ext4:
umount /var/lib/mysql(确保 mysqld 已停)→e2fsck -f /dev/sdXN(设备名需替换)→ 修复后mount /var/lib/mysql - 如果是 XFS:
xfs_repair /dev/sdXN(XFS 不支持在线修复,必须 umount) - 注意:若
e2fsck提示 “journal has been deleted”,说明 journal 损坏严重,需加-c参数扫描坏块;xfs_repair若报 “cannot initialize list” 可能需先用xfs_db -r手动 inspect
恢复 MySQL 后的关键动作
文件系统修复并重新 mount 为 rw 后,MySQL 不会自动退出只读状态——它已进入“自我保护锁死”模式:
- 启动 mysqld 前,**必须清除残留的 socket 和 pid 文件**:
rm -f /var/lib/mysql/mysql.sock /var/lib/mysql/*.pid,否则 systemd 可能因旧 PID 冲突拒绝启动 - 启动后立刻检查:
SELECT @@global.read_only, @@global.super_read_only;—— 正常应全为0;若仍为1,说明 mysqld 启动时检测到上次异常,需手动重置:SET GLOBAL read_only = OFF; SET GLOBAL super_read_only = OFF; - 执行
SHOW ENGINE INNODB STATUS\G,重点看FILE I/O和LOG段是否仍有pending或error,若有,说明 redo log 或 ibdata1 损坏尚未暴露,需进一步用innodb_force_recovery导出数据 - 别忽略
ib_logfile*:文件系统错误常连带损坏 redo log,即使服务起来,也可能在后续 checkpoint 时崩溃。稳妥做法是删除ib_logfile0和ib_logfile1(mysqld 停止状态下),让 InnoDB 重建
为什么不能跳过文件系统检查直接调参?
因为 InnoDB 的只读状态在此类场景下是结果,不是原因。强行设 innodb_read_only = OFF 或 read_only = OFF 会掩盖真实风险:
- 写操作看似成功,实则被内核丢弃(无报错,但数据不落盘)
- 下次 reboot 或 journal replay 时,数据库大概率无法启动,且损坏扩大
-
innodb_force_recovery在文件系统只读下根本无法启用——它需要写临时文件和内存结构,而底层open(O_RDWR)会直接失败 - 备份工具(如
mysqldump)可能导出空数据或中途静默退出,你以为救回来了,其实没数据
真正的修复起点永远是 dmesg 和 mount 输出,而不是 MySQL 的 SQL 提示。











