GRANT报Access denied主因是执行者缺少GRANT OPTION权限,而非语句错误;需用SHOW GRANTS FOR CURRENT_USER()确认是否含WITH GRANT OPTION,缺失则执行GRANT ALL PRIVILEGES ON . TO 'root'@'localhost' WITH GRANT OPTION;并FLUSH PRIVILEGES。

GRANT报Access denied:执行者缺GRANT OPTION
不是语句写错了,而是你登录用的那个用户没被允许“给别人授权”。MySQL把“使用权限”和“授予权限”拆成两套开关,GRANT OPTION必须显式加上,否则哪怕你是root@'localhost',执行GRANT也会直接报ERROR 1045 (28000): Access denied。
验证方式只有一种:SHOW GRANTS FOR CURRENT_USER();。如果输出里没出现WITH GRANT OPTION,就说明当前会话无权执行授权操作。
- 补权限要带
WITH GRANT OPTION,比如:GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION; - 改完后建议执行
FLUSH PRIVILEGES;,尤其在MySQL 5.7之前或直改mysql.user表后 - 注意:
GRANT ALL PRIVILEGES本身不包含GRANT OPTION,这是常见误解
MySQL 8.0+下GRANT报语法错误:IDENTIFIED BY已被移除
如果你的SELECT VERSION();返回的是8.0.x或更高版本,所有把用户创建和授权写在一条GRANT里的写法都会失败——比如GRANT SELECT ON db.* TO 'u'@'%' IDENTIFIED BY 'pwd';,这在5.7能跑,但在8.0+会触发ERROR 1064或ERROR 1410。
必须拆成两步,且顺序不能错:
- 先创建用户:
CREATE USER 'u'@'%' IDENTIFIED BY 'pwd'; - 再赋权:
GRANT SELECT ON db.* TO 'u'@'%';(这里绝不能加IDENTIFIED BY) - 若用户已存在,密码要改用:
ALTER USER 'u'@'%' IDENTIFIED BY 'newpwd';
权限“看起来给了”,但新用户连不上或查不了表
执行完GRANT后别急着测试连接,先确认三件事:
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
- 目标用户是否存在:
SELECT User, Host FROM mysql.user WHERE User = 'u';,如果查不到,说明CREATE USER根本没成功 - host是否精确匹配:授权是
'u'@'192.168.1.%',但应用连的是'u'@'192.168.1.100',没问题;但如果连的是'u'@'localhost',那就完全不匹配 - 权限是否落在正确作用域:
SHOW GRANTS FOR 'u'@'%';输出里必须有对应库/表的权限条目,而不是只看到USAGE或者空
特别注意:localhost和127.0.0.1在MySQL里是两个独立host,不能互相替代。
GRANT后权限不生效:底层权限表被隐式拒绝
SHOW GRANTS显示权限已给,但实际操作仍报错,可能是更细粒度的拒绝规则在起作用——比如有人手动往mysql.tables_priv或mysql.columns_priv里插了DENY记录,这些不会出现在SHOW GRANTS里。
排查方式:
- 查表级限制:
SELECT * FROM mysql.tables_priv WHERE User = 'u' AND Host = '%' AND Db = 'mydb' AND Table_name = 't1'; - 查列级限制:
SELECT * FROM mysql.columns_priv WHERE User = 'u' AND Host = '%' AND Db = 'mydb' AND Table_name = 't1'; - 只要结果非空,且
Column_name或Table_priv字段含N或空值,就可能覆盖掉你给的GRANT
这类问题最容易被忽略,因为日志里不报错,SHOW GRANTS也一切正常,但行为就是不对——权限系统按层级匹配,最近一条有效规则才生效。










