mysql报错“table is read only”的真实原因是mysql进程无法对表文件执行写操作,常见于文件系统权限不足、磁盘只读挂载、mysql服务级只读配置启用、或selinux/apparmor强制访问控制拦截。

MySQL报错 Table is read only 的真实原因
这个错误不是表本身被设为只读,而是 MySQL 进程无法对表文件(.ibd 或 .MYD)执行写操作。常见触发点是文件系统权限、磁盘只读挂载、或 MySQL 自身的只读开关被意外启用。
检查并修复文件系统级权限和挂载状态
MySQL 进程(通常是 mysql 用户)必须对数据目录(如 /var/lib/mysql/yourdb/)及其下所有文件拥有读写权限,且所在分区不能是只读挂载。
- 用
ls -ld /var/lib/mysql/yourdb/确认目录属主是mysql:mysql,权限至少含drwxr-x--- - 运行
mount | grep "$(df . | tail -1 | awk '{print $1}')"查看该分区是否带ro(read-only)标志 - 若挂载为只读,需查清原因:磁盘错误(
dmesg | tail看是否有 I/O 错误)、文件系统损坏(sudo e2fsck -n /dev/sdXN预检)、或人为mount -o remount,ro - 临时修复只读挂载:仅当确认安全时执行
sudo mount -o remount,rw /mount/point;但务必先排查底层故障
确认 MySQL 服务级只读配置未被误启
即使文件系统正常,read_only=ON 全局变量或 super_read_only=ON 也会让所有表表现为只读(除 super 用户外)。
- 登录 MySQL 后执行
SELECT @@read_only, @@super_read_only;,两者都应为0 - 检查配置文件(
/etc/my.cnf或/etc/mysql/mysql.conf.d/mysqld.cnf),确认没有read_only = 1或super_read_only = 1行 - 如果从库开启了
read_only,但当前实例不是从库,要检查是否误配了复制相关参数(如relay_log_recovery=ON导致启动时自动设只读)
验证表文件所有权和 SELinux/AppArmor 干扰
Linux 发行版常启用强制访问控制(SELinux 或 AppArmor),即使权限正确,也可能拦截 MySQL 的写入行为。
- CentOS/RHEL 上运行
sudo ls -Z /var/lib/mysql/yourdb/yourtable.ibd,确认上下文为system_u:object_r:mysqld_db_t:s0;否则用sudo semanage fcontext -a -t mysqld_db_t "/var/lib/mysql(/.*)?"+sudo restorecon -Rv /var/lib/mysql - Ubuntu/Debian 上检查
sudo aa-status | grep mysql,若 AppArmor 正在限制,临时禁用测试:sudo ln -s /etc/apparmor.d/usr.sbin.mysqld /etc/apparmor.d/disable/+sudo apparmor_parser -R /etc/apparmor.d/usr.sbin.mysqld - 注意:不要直接
chown -R root:mysql数据目录——MySQL 启动失败或拒绝加载表
最常被忽略的是挂载状态和 SELinux 上下文,尤其在云主机重装系统或手动迁移数据后;改权限前先 mysqld --validate-config 检查配置合法性,避免重启失败。











