SET GLOBAL read_only = ON 对监控账号无效,因其通常拥有SUPER或SYSTEM_USER权限,而该参数仅限制普通用户;必须显式授予最小必要权限(如PROCESS、REPLICATION CLIENT等)并回收高权限,才能实现真正只读与可靠监控。

监控账号不能只靠 read_only=ON 实现“只读”,它本身就不限制该账号——必须显式授予最小必要权限,否则采集会失败或越权。
为什么 SET GLOBAL read_only = ON 对监控账号无效
这个变量只拦普通用户写操作,而监控账号(如 monitor、mha_monitor)通常带 SUPER 或 SYSTEM_USER 权限,属于豁免名单。即使你开了 read_only,它照样能执行 INSERT INTO metrics_log 或 FLUSH LOGS —— 这不是 bug,是 MySQL 的设计逻辑。
更危险的是:某些自研采集脚本会顺手写日志表,一旦用了高权限账号又没做权限隔离,升级/维护时就可能偷偷写入,破坏数据一致性。
-
read_only不影响复制线程、SUPER用户、事件调度器(除非用SUPER创建) - MySQL 8.0+ 的
super_read_only虽能锁死SUPER用户,但它同时禁止UNLOCK TABLES,和运维常用命令冲突 - 云厂商 RDS(如阿里云)可能直接禁用该变量写入,执行报错:
Variable 'read_only' is a read only variable
GRANT 必须精确到权限项,不能靠 ALL PRIVILEGES 或 SELECT 单项撑场面
监控不是“查几张表”那么简单。mysqld_exporter、Zabbix、Orchestrator 等工具依赖多个系统库和状态指令,缺一不可:
-
SELECT:查information_schema(连接数、表结构)、performance_schema(锁、等待、语句耗时) -
PROCESS:运行SHOW PROCESSLIST,否则只能看到自己的会话,慢查询和阻塞线程全漏掉 -
REPLICATION CLIENT:执行SHOW SLAVE STATUS和SHOW MASTER STATUS,没它就看不到复制延迟 - 额外补充:
SELECT ON performance_schema.*(很多指标默认不开放给非root)
别信 GRANT SELECT ON *.* —— 它不包含 PROCESS 和 REPLICATION CLIENT,这两项是独立管理类权限,必须显式写出。
监控 Victron Energy 电力系统,生成包含电池状态、光伏发电量和活动警报的精美每日邮件报告。集成 Vic...
错误示例:GRANT SELECT ON *.* TO 'monitor'@'192.168.10.%';
→ 执行 SHOW PROCESSLIST 时会报:Access denied; you need (at least one of) the PROCESS privilege(s) for this operation
创建账号时的三个易踩坑点
权限配置失败,80% 出在账号创建阶段,而不是 GRANT 本身:
-
CREATE USER必须先于GRANT:MySQL 8.0+ 不再允许隐式建用户,GRANT前没CREATE USER就报错:ERROR 1133 (HY000): Can't find any matching row in the user table - 主机名要匹配真实来源:监控服务若跑在容器里,实际 IP 是
172.18.0.5,但账号建的是'monitor'@'10.0.0.11',连接直接被拒;建议用网段(如'monitor'@'192.168.10.%')或域名(确保 DNS 同步) - 认证插件不兼容:MySQL 8.0 默认用
caching_sha2_password,而mysqld_exporter v0.12.x及更老版本只认mysql_native_password,连不上且报错:plugin caching_sha2_password is not loaded;建号时得指定:CREATE USER 'monitor'@'%' IDENTIFIED WITH mysql_native_password BY 'xxx';
验证是否真“只读”且“可监控”
别只看 SHOW GRANTS 输出,要模拟工具行为实测:
- 用账号连上去,手动执行监控常用语句:
SHOW PROCESSLIST;SHOW SLAVE STATUS\GSELECT * FROM performance_schema.events_statements_history_long LIMIT 1;
任一失败,说明权限缺项 - 反向验证“只读”:尝试
INSERT INTO mysql.user VALUES ();或DROP DATABASE test;,应明确报错ERROR 1290 (HY000): The MySQL server is running with the --read-only option so it cannot execute this statement或权限拒绝 - 检查连接是否走对协议:如果 MySQL 配了
require_secure_transport=ON,而监控端没配 TLS,连接会被静默拒绝,mysqld_exporter日志只显示 timeout
最常被忽略的一点:权限改完必须 FLUSH PRIVILEGES;,否则新授权不生效;而 CREATE USER + GRANT 组合在 8.0+ 中虽多数情况自动刷新,但跨版本迁移或从备份恢复后,仍建议显式执行一次。

















