grant all on . 不是跨库授权,而是全局权限;正确做法是分多条grant语句显式授予各目标库权限,如grant select on sales. to 'user'@'host'; grant select on inventory. to 'user'@'host'; 并用反引号包裹通配符库名。

GRANT ALL ON *.* 是跨库授权吗
不是。它确实是“所有数据库所有表”,但本质是全局权限,不等于跨库访问控制所需的最小权限集。真正跨库场景下,用户往往只需要访问几个指定库(比如 sales 和 inventory),而不是整个实例。用 ALL ON *.* 会绕过库级权限检查,也违反最小权限原则,还可能被安全审计直接否决。
给用户同时授权多个数据库的正确写法
MySQL 不支持一条 GRANT 语句里写多个数据库名,必须拆成多条语句,每条对应一个库。否则会报错 ERROR 1064 (42000) 或权限未生效。
- 先确保用户已存在(MySQL 5.7 虽可隐式创建,但显式
CREATE USER更可控):CREATE USER 'reporter'@'192.168.1.%' IDENTIFIED BY 'p@ssw0rd';
- 再逐库授权(注意末尾的
.*不能省):GRANT SELECT, EXECUTE ON sales.* TO 'reporter'@'192.168.1.%';<br>GRANT SELECT, EXECUTE ON inventory.* TO 'reporter'@'192.168.1.%';
- 最后刷新权限:
FLUSH PRIVILEGES;
用通配符匹配数据库名时的坑
MySQL 允许在 GRANT 的数据库名位置使用 % 和 _,但仅限于数据库名本身,且必须用反引号包裹,否则语法错误或匹配失败。
- 想授权所有以
log_开头的库:GRANT SELECT ON `log_%`.* TO 'logger'@'localhost';
- 反引号不可省略:写成
log_%.*会被当作文本字面量,导致权限不生效 -
_是单字符通配符,`log__`匹配log_a、log_1,但不匹配log_test - 通配符只在
GRANT语句中有效;查询mysql.db表时看到的是展开后的实际库名,不是模式
跨库查询失败但权限看似正常?检查 EXECUTE 和 DEFINER
如果用户能查 sales.orders,却无法执行 inventory.get_stock() 存储过程,大概率缺 EXECUTE 权限,或该过程定义为 DEFINER = 'root'@'localhost' 且用户没被授予 PROXY 权限。
- 存储过程/函数/视图跨库调用,目标库需显式授
EXECUTE或SELECT:GRANT EXECUTE ON FUNCTION inventory.get_stock TO 'reporter'@'192.168.1.%';
- 若过程用
SQL SECURITY DEFINER,调用者权限不继承,必须确保DEFINER用户存在且有对应权限,或改用SQL SECURITY INVOKER - 权限验证别只信
SHOW GRANTS,用实际账号登录后执行SELECT * FROM sales.orders LIMIT 1;和CALL inventory.get_stock();双重确认
通配符授权看着方便,但一旦数据库名含下划线或百分号,反引号漏一个就全挂;跨库调用存储过程时,EXECUTE 权限和 DEFINER 模式这两处最容易被忽略。











