跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

mysql为什么设置了从库只读仍能写入_分析root用户特殊权限

read_only=ON拦不住root,因其是“高权限豁免型”只读机制:root默认拥有SUPER和SYSTEM_VARIABLES_ADMIN权限,而该参数仅限制无此权限的普通用户,不构成强制访问控制。 MySQL 从库设了
read_only=ON
,root 还能写,不是配置失效,是权限设计如此。 为什么
read_only=ON
拦不住 root? 因为
read_only
不是权限开关,而是“高权限豁免型”只读保护:只要用户拥有
SUPER
或
SYSTEM_VARIABLES_ADMIN
权限,就能绕过该限制。MySQL 8.0.12+ 默认给
root@localhost
同时授予这两个权限,所以即使
SHOW VARIABLES LIKE 'read_only'
返回
ON
,
INSERT
/
UPDATE
依然成功。 普通用户(如
repl_user
)没显式授这俩权限,就会被拦住,报错:
The MySQL server is running with the --read-only option so it cannot execute this statement
read_only
是会话级检查,不校验账号角色,也不管你是不是复制线程——它只看当前连接用户的系统权限 云厂商 RDS 常默认关闭
read_only
,且禁止动态修改,得走控制台或白名单申请
super_read_only=ON
才真能锁死 root
super_read_only
是 MySQL 5.7.20+ / 8.0+ 引入的强化版只读开关,启用后连
SUPER
用户也无法执行 DML/DDL,且该变量不可动态关闭(除非先关它自己)。 必须在配置文件
my.cnf
的
[mysqld]
段落中写死:
super_read_only=ON
;仅靠
SET GLOBAL super_read_only = ON
不可靠,重启即失效 MySQL 8.0.26+ 有联动机制:一旦
super_read_only=ON
,
read_only
自动强制为
ON
;但反过来不成立 注意陷阱:
SET GLOBAL super_read_only = OFF
只需
SYSTEM_VARIABLES_ADMIN
权限,不需要
SUPER
——所以这个变量本身也要靠权限回收来守 真正封死写入的三步操作 单靠一个参数永远不够,必须组合加固: MySQL(Linux) MySQL 9.6.0是面向Linux平台的2026年创新版本,核心架构迎来重大革新。其将外键约束与级联操作从InnoDB引擎层上移至SQL层,确保所有数据变更均被完整记录至Binlog,彻底解决了CDC(变更数据捕获)与主从复制中的数据不一致难题。此外,该版本引入container_aware启动选项以原生适配容器环境,并对审计日志进行了组件化重构,为追求极致数据一致性与云原生体验的开发者提供了全新选择。 下载 在
my.cnf
中同时设置:
read_only=ON
和
super_read_only=ON
,然后重启
mysqld
或用
SET PERSIST super_read_only = ON
(需
PERSIST_RO_VARIABLES_ADMIN
权限) 回收 root 的越权能力:
REVOKE SUPER ON *.* FROM 'root'@'localhost';
,MySQL 8.0.12+ 还要追加:
REVOKE SYSTEM_VARIABLES_ADMIN ON *.* FROM 'root'@'localhost';
验证是否生效:
SHOW GRANTS FOR 'root'@'localhost';
输出里不能出现
SUPER
或
SYSTEM_VARIABLES_ADMIN
;再试
INSERT
,应报错
ERROR 1290 (HY000): The MySQL server is running with the --super-read-only option so it cannot execute this statement
容易被忽略的“伪只读”行为 即使
super_read_only=ON
生效,某些命令仍会产生 binlog 记录、改变 GTID 状态,造成主从逻辑不一致:
FLUSH TABLES
、
ANALYZE TABLE
、
OPTIMIZE TABLE
等语句会被写入 binlog(除非显式加
NO_WRITE_TO_BINLOG
),产生新 GTID,导致
@@global.gtid_executed
在主从上不一致
super_read_only
不影响
SELECT
、
SET
变量、
SHOW
类命令,也不阻止 relay log 自动 purge(
relay_log_purge=ON
必须单独确认) 如果从库意外开启了
log_bin
,误写 + binlog 开启 = 错误数据可能被同步到下游,必须定期查
SHOW VARIABLES LIKE 'log_bin'
并确保为
OFF
最常被漏掉的一点:权限回收后没验证复制线程是否还能跑。SQL_THREAD 需要
REPLICATION SLAVE
权限,但不需要
SUPER
;只要没误 revoke 这个权限,且
relay_log_purge=ON
,从库就能持续同步——否则“只读”只是表象,实际已静默脱同步。

相关文章