必须搭配super_read_only=on并重启生效,否则root等super用户仍可删表写入;因read_only仅限制非super用户,是设计行为而非配置失败,需在[mysqld]段按序配置两参数、收紧账号权限并验证复制状态。

只靠 read_only = ON 不行,必须搭配 super_read_only = ON 并重启生效,否则 root 或监控账号仍能写入。
为什么 read_only = ON 后 root 还能删表?
这是 MySQL 的设计行为,不是配置失败。read_only 默认只限制非 SUPER 权限用户;root、DBA 账号、常用监控脚本账号通常自带 SUPER 权限,可直接绕过该限制。你看到 SHOW VARIABLES LIKE 'read_only' 返回 ON,不代表写操作被拦住——它只是变量值,不等于权限锁死。
如何让只读真正持久且全局生效?
必须在 my.cnf(或 mysqld.cnf)的 [mysqld] 段下顺序写入:
read_only = ON super_read_only = ON
注意以下要点:
- 不能颠倒顺序:
super_read_only依赖read_only开启才有效 - 不能写错节名:必须放在
[mysqld]下,[client]或[mysql]会被静默忽略 - 值必须是
ON或OFF(大小写不敏感,但推荐大写),不能用1、true、yes - MySQL 8.0.22+ 可用
SET PERSIST super_read_only = ON自动写入mysqld-auto.cnf,适合容器环境 - 必须执行
systemctl restart mysqld,mysqladmin reload不生效
哪些写操作 super_read_only 也拦不住?
即使两个变量都为 ON,以下操作仍可能隐式写入,破坏只读语义:
-
FLUSH LOGS、RESET MASTER:不改业务表,但会破坏复制一致性 -
CREATE TEMPORARY TABLE:临时表不受read_only约束 - 修改系统表(如
mysql.user):当账号有UPDATE权限时可执行 - 调用含写逻辑的存储函数:若函数未声明
READS SQL DATA,且内部执行了INSERT,就会绕过检查
所以光靠变量不够,还得配合最小权限原则:从库账号只给 SELECT、REPLICATION CLIENT、PROCESS,砍掉所有 DML/DCL 权限。
怎么验证只读是否真生效?
别只信 SHOW VARIABLES。要用实际业务账号登录,执行:
INSERT INTO test_table VALUES (1);
应报错:
ERROR 1290 (HY000): The MySQL server is running with the --read-only option so it cannot execute this statement
同时确认复制状态正常:
SHOW SLAVE STATUS\G
确保 Slave_IO_Running 和 Slave_SQL_Running 均为 Yes——如果复制已停止,只读就失去意义。
最易被忽略的是:配置后没验证高权限账号行为,也没检查复制线程是否存活。只要其中一环断开,所谓“只读”就是假象。











