不能只靠read_only=ON限制监控账号,因为read_only仅拦截DML/DDL写操作,对SHOW SLAVE STATUS等管理语句无效,也不限制SELECT查数据;必须组合授予REPLICATION CLIENT、PROCESS及特定schema的SELECT权限,并配合super_read_only=ON彻底阻断写入。

只能查复制状态、不能写、不能看数据——这种账号必须用最小权限组合,而不是靠 read_only 挡着。
为什么不能只靠 read_only=ON 限制监控账号
因为 read_only 只拦 DML/DDL,对 SHOW SLAVE STATUS、SHOW MASTER STATUS 这类管理语句完全无效;它也不限制账号查看表数据。一个被授予 SELECT 权限的账号,哪怕实例开了 read_only,照样能 SELECT * FROM user —— 这不是你想要的“纯监控”。
该给监控账号哪些权限(MySQL 5.7+)
只授予明确需要的全局权限,不碰库表级权限:
-
REPLICATION CLIENT:必需,用于执行SHOW SLAVE STATUS、SHOW MASTER STATUS -
PROCESS:可选,用于SHOW PROCESSLIST查看线程状态(如 IO/SQL 线程是否卡住) -
SELECT(仅限performance_schema或information_schema中必要视图):比如查replication_applier_status_by_coordinator,但不要给SELECT ON *.* - 绝对不授:
SUPER、REPLICATION SLAVE、CREATE、INSERT、UPDATE、DELETE、GRANT OPTION
建号示例:
CREATE USER 'monitor_replica'@'192.168.10.%' IDENTIFIED BY 'StrongPass2026!'; GRANT REPLICATION CLIENT, PROCESS ON *.* TO 'monitor_replica'@'192.168.10.%'; GRANT SELECT ON performance_schema.replication_applier_status TO 'monitor_replica'@'192.168.10.%'; FLUSH PRIVILEGES;
验证账号真没越权能力
别只测 SHOW SLAVE STATUS 成功就完事。登录后实测几项关键边界:
- 执行
SELECT @@read_only→ 应成功(只读变量可查) - 执行
SELECT COUNT(*) FROM mysql.user→ 应报错ERROR 1142 (42000): SELECT command denied - 执行
STOP SLAVE→ 应报错ERROR 1227 (42501): Access denied; you need (at least one of) the SUPER or REPLICATION_SLAVE_ADMIN privilege(s) - 执行
INSERT INTO test.t1 VALUES(1)→ 应报错ERROR 1290 (HY000): The MySQL server is running with the --read-only option...(注意:这个错误其实是read_only在起作用,不是权限拒绝,说明账号没被误授写权限)
配套配置必须同步做
账号权限只是半截腿。真正锁死风险,还得靠实例层配合:
- 从库必须启用
super_read_only = ON(不只是read_only),否则带SUPER权限的账号能绕过一切权限检查直接写 - 监控脚本里避免任何隐式写操作:比如
CREATE TEMPORARY TABLE、SET SESSION sort_buffer_size = ...都可能触发read_only拒绝,应全用纯SELECT+SHOW - 如果用 Prometheus + mysqld_exporter,确保其连接用户就是这个
monitor_replica,且 exporter 配置里没开collect.slave_status以外的高危采集项
最易忽略的一点:很多监控脚本默认会执行 SELECT NOW() 或 SELECT @@version,这些没问题;但一旦脚本里混了 INSERT INTO monitor_log ... 就直接崩,这类逻辑必须剥离或改用外部日志系统记录。


















