grant语句按对象层级(全局/数据库/表/列)和权限类型精确授权,常用数据库级如grant select,insert on myapp.*;需注意权限追加不覆盖、ip限制、flush privileges及mysql 8.0角色管理。

GRANT 语句的基本语法和权限粒度
MySQL 的 GRANT 不是“给用户赋一个笼统权限”,而是按「对象层级 + 权限类型」精确控制。常见错误是直接写 GRANT ALL PRIVILEGES ON *.*,结果发现新用户连 SELECT 都被拒绝——因为没加 WITH GRANT OPTION 或漏了 FLUSH PRIVILEGES。
权限作用域分四层:全局(*.*)、数据库级(db_name.*)、表级(db_name.table_name)、列级((col1,col2))。实际中 90% 场景用前两层就够了。
-
GRANT SELECT, INSERT ON myapp.* TO 'appuser'@'192.168.1.%'—— 最常用,限制 IP 段比'%'更安全 -
GRANT USAGE ON *.* TO 'monitor'@'localhost'—— 仅允许连接,不授任何操作权限 - 不能对已存在的用户重复
GRANT覆盖旧权限;它只追加,要重置得先REVOKE
常见报错与对应修复
执行 GRANT 报错,八成不是语法问题,而是权限或状态没到位:
-
Error 1410 (42000): You are not allowed to create a user with GRANT→ 当前登录用户没CREATE USER权限,改用已有用户或用 root 执行 -
ERROR 1045 (28000): access denied for user→ 执行GRANT的账户本身没GRANT OPTION,检查SHOW GRANTS FOR CURRENT_USER - 授权后应用仍连不上 → 忘了
FLUSH PRIVILEGES(MySQL 5.7+ 多数情况自动刷新,但跨主机或特殊配置下仍需手动) - 用户从远程连不上 → 检查
bind_address是否为127.0.0.1(只监听本地),需改为0.0.0.0或具体内网 IP
生产环境推荐的最小权限示例
给 Web 应用账号配权限,原则是「够用且不可越界」。下面这个配置覆盖典型 CRUD 场景,不含危险操作:
GRANT SELECT, INSERT, UPDATE, DELETE ON myapp_db.* TO 'webapp'@'10.0.2.%' IDENTIFIED BY 'strong_password_2024'; GRANT EXECUTE ON PROCEDURE myapp_db.calc_report TO 'webapp'@'10.0.2.%'; FLUSH PRIVILEGES;
说明:
- 不用
ALL PRIVILEGES,禁用DROP、ALTER、CREATE等高危权限 - 密码用
IDENTIFIED BY直接设置,避免分CREATE USER+GRANT两步(MySQL 8.0+ 推荐用CREATE USER单独建,再GRANT) - 限定来源 IP 段(
10.0.2.%)比%安全得多;若用容器或云服务,注意宿主机网络模式是否影响 IP 判定
MySQL 8.0+ 的角色(ROLE)替代方案
频繁给多个用户配相同权限?别硬写一堆 GRANT。MySQL 8.0 支持角色管理,更易维护:
CREATE ROLE 'app_reader'; GRANT SELECT ON myapp_db.* TO 'app_reader'; GRANT 'app_reader' TO 'report_user'@'%'; SET default ROLE 'app_reader' TO 'report_user'@'%';
关键点:
- 角色本身不登录,只是权限容器;必须显式用
GRANT role_name TO user绑定 - 用户启用角色需
SET DEFAULT ROLE,否则登录后权限不生效 - 角色不能嵌套(即不能
GRANT role_a TO role_b) - 老版本(GRANT 语句
权限配置真正麻烦的不是语法,而是理清「谁在什么网络环境下访问什么数据」。IP 白名单、密码强度、权限回收时机,这些比 GRANT 本身更常出问题。