grant all privileges本身不包含grant option,必须显式添加with grant option才能赋予转授权限;mysql 8.0+需先create user再grant,且grant option仅在其对应权限作用域内生效。

因为 GRANT ALL PRIVILEGES 本身不包含 GRANT OPTION,必须显式加上它,否则用户根本没有“授予权限”的能力——哪怕你给了他所有操作权限。
GRANT ALL 不等于能 GRANT
这是最常被踩的坑:MySQL 把“使用权限”(如 SELECT、INSERT)和“授予权限”(即 GRANT OPTION)完全解耦。就算你执行了:
GRANT ALL PRIVILEGES ON *.* TO 'u'@'%';
该用户依然无法对别人执行任何 GRANT 语句。
-
SHOW GRANTS FOR 'u'@'%'输出里若没有WITH GRANT OPTION,就说明没开通转授权 - 用户执行
GRANT SELECT ON db.* TO 'other'@'localhost'会直接报错ERROR 1045 (28000): Access denied - 修复只需补上选项:
GRANT ALL PRIVILEGES ON *.* TO 'u'@'%' WITH GRANT OPTION;
MySQL 8.0+ 必须先 CREATE USER 再 GRANT
在 MySQL 8.0 及更高版本(包括当前最新的 9.6.0),GRANT ... IDENTIFIED BY 语法已被彻底移除。老写法会触发 ERROR 1064 或 ERROR 1410:
GRANT ALL ON *.* TO 'u'@'%' IDENTIFIED BY 'pwd' WITH GRANT OPTION; ❌
正确流程只有两步,顺序不能颠倒:
- 先创建账户:
CREATE USER 'u'@'%' IDENTIFIED BY 'pwd'; - 再赋权:
GRANT ALL PRIVILEGES ON *.* TO 'u'@'%' WITH GRANT OPTION; - 建议追加:
FLUSH PRIVILEGES;(虽多数情况自动刷新,但跨主机或批量操作时容易漏生效)
WITH GRANT OPTION 的作用域极窄
GRANT OPTION 不是全局通行证,它严格绑定在当前 GRANT 语句声明的权限范围和对象上。
- 比如:
GRANT SELECT, INSERT ON app_db.* TO 'dev'@'localhost' WITH GRANT OPTION; - 那么
dev只能将SELECT和INSERT授给他人,且仅限于app_db下的表 - 他不能授
UPDATE,也不能授mysql.user表,更不能授CREATE DATABASE—— 即使他自己有这些权限,也无权转授 - 想让某人能授予任意权限?必须给
ALL PRIVILEGES ON *.* WITH GRANT OPTION,缺一不可
最容易被忽略的是:多个 GRANT 语句不会自动合并 GRANT OPTION。比如你分两次给 SELECT 和 INSERT 权限,但只在其中一条加了 WITH GRANT OPTION,那用户只能转授那一项——其余权限仍不可转授。











