只读用户必须显式拒绝写权限,不能只靠 GRANT SELECT
MySQL 的权限模型是“显式授权”,
GRANT SELECT不代表自动禁止
INSERT/
UPDATE/
DELETE;如果用户之前被授予过全局或库级写权限(比如通过
GRANT ALL PRIVILEGES),仅执行
GRANT SELECT不会撤销已有权限。必须先
REVOKE写操作权限,再
GRANT SELECT。
常见错误现象:用户仍能执行
DELETE FROM t1,即使你只运行了
GRANT SELECT ON db1.* TO 'ro_user'@'%'—— 很可能该用户继承了
mysql.user表中残留的旧权限。 检查当前权限:运行
SHOW GRANTS FOR 'ro_user'@'%'彻底清理:先执行
REVOKE INSERT, UPDATE, DELETE, DROP, CREATE, ALTER, INDEX, LOCK TABLES, EXECUTE ON *.* FROM 'ro_user'@'%'再授只读:
GRANT SELECT ON `db1`.* TO 'ro_user'@'%'最后别忘:
FLUSH PRIVILEGES
跨库查询时只读权限不自动继承
SELECT权限是按库/表粒度控制的。用户对
db1有
SELECT权限,不代表能查
db2,也不代表能查
db1中的
INFORMATION_SCHEMA或
performance_schema—— 这些系统库需单独授权(通常不建议开放)。
使用场景:应用连接后执行
SELECT * FROM db2.t2报错
ERROR 1142 (42000): SELECT command denied to user,但用户明明在
db2上跑过
USE db2。 若需跨多个业务库只读,逐个授权:
GRANT SELECT ON `db2`.* TO 'ro_user'@'%'避免用
GRANT SELECT ON *.*(等同于所有库可读,含敏感系统库) 注意反引号:库名含短横线或关键字时必须用
`db-name`,否则语法报错
只读用户无法执行 SHOW CREATE TABLE?检查 USAGE + SELECT 组合
很多 ORM 或监控工具会尝试执行
SHOW CREATE TABLE t1或
SHOW FULL COLUMNS FROM t1。这类语句底层依赖
SELECT权限(查
information_schema表),但 MySQL 8.0+ 对
information_schema的访问受更细粒度限制。
典型错误:用户能
SELECT * FROM t1,但执行
SHOW CREATE TABLE t1报
ERROR 1142 (42000): SHOW command denied to user。 MySQL 5.7:确保用户对
information_schema有
SELECT(默认所有用户都有,除非显式
REVOKE过) MySQL 8.0+:
information_schema默认不可写,但部分元数据操作需
USAGE+ 显式
SELECT;稳妥做法是加一句:
GRANT SELECT ON `information_schema`.`TABLES` TO 'ro_user'@'%'注意:不要授
information_schema全库,只需
TABLES、
COLUMNS、
STATISTICS等必要表
应用连接后仍报权限错误?检查 host 匹配和 SQL_MODE
权限记录由
User+
Host共同决定。
'ro_user'@'localhost'和
'ro_user'@'%'是两个完全独立的账号,哪怕密码相同,权限也互不影响。另外,某些 SQL_MODE(如
STRICT_TRANS_TABLES)虽不直接影响权限,但会让隐式类型转换失败,误判为“无权访问”。 确认连接来源 IP 是否匹配
Host字段(用
SELECT USER(), CURRENT_USER()查看实际匹配的账号) 测试时用
mysql -u ro_user -h 127.0.0.1 -p(走 TCP)而非
mysql -u ro_user -p(走 socket,默认 host= localhost) 检查是否启用了
read_only=ON全局设置:它只限制非 SUPER 用户的写操作,但不会替代细粒度权限控制;两者应配合使用,而非互相替代
复杂点在于权限生效链路:SQL 解析 → 账号匹配 → 权限查表(mysql.tables_priv / mysql.columns_priv / mysql.db)→ 缓存校验。中间任何一环配置偏差,都会导致“明明授了权却没效”。最易忽略的是
CURRENT_USER()返回值与预期不符,以及未执行
FLUSH PRIVILEGES后直接测试。
