ERROR 1064说明未使用MySQL 8.0+,因角色功能自8.0.0引入;须先执行SELECT VERSION()确认版本≥8.0.1,再检查CREATE ROLE权限、禁用反引号、避免角色名与用户名冲突。

CREATE ROLE 报 ERROR 1064 怎么办
直接报错,说明你根本没在用 MySQL 8.0+。角色功能是 8.0.0 引入的,5.7 或更低版本执行 CREATE ROLE 必然触发 ERROR 1064 (42000)。先跑一句 SELECT VERSION(); 确认输出是 8.0.x 或更高。
如果版本没问题还报错,检查三件事:
- 当前用户是否拥有
CREATE ROLE权限(普通 DBA 账号默认没有,需 root 授予) - 别用反引号包角色名:
CREATE ROLE `app_reader`是错的,应写成CREATE ROLE 'app_reader'或CREATE ROLE app_reader - 角色名不能和已有用户名冲突,比如已有
'admin'@'%',再CREATE ROLE 'admin'就会失败
GRANT 角色给用户后 SELECT 还是 Access denied
因为 GRANT 'app_reader' TO 'webapp'@'10.20.30.%' 只是绑定关系,不等于激活。用户登录后 CURRENT_ROLE() 返回 NONE,所有权限都不可见。
必须补上这句才能生效:SET DEFAULT ROLE 'app_reader' TO 'webapp'@'10.20.30.%'。
连接池场景下尤其容易翻车:
- HikariCP、Druid 等默认不执行初始化 SQL,得显式配置
connection-init-sql="SET DEFAULT ROLE 'app_reader'" - 或通过 JDBC URL 加参数:
sessionVariables=default_role=app_reader - 一个用户可授多个角色,但
SET DEFAULT ROLE ALL TO容易违反最小权限原则,慎用
SHOW GRANTS 为什么看不到角色权限
不是漏授权,是设计如此。SHOW GRANTS FOR 'webapp'@'10.20.30.%' 只显示直接授予用户的权限(比如 USAGE),完全不展开角色继承的权限。
要查角色实际赋予的权限,有两种办法:
- 用
USING子句:SHOW GRANTS FOR 'webapp'@'10.20.30.%' USING 'app_reader' - 登录后查系统表:
SELECT * FROM INFORMATION_SCHEMA.ROLE_TABLE_GRANTS WHERE GRANTEE = '''webapp''@''10.20.30.%''' AND ROLE_NAME = 'app_reader'
mysql.role_edges 表记录分配关系,但普通账号无权访问,只有 root 或有 SELECT ON mysql.* 的账号能查。
动态权限怎么和角色配合使用
像 session_variables_admin、BINLOG_ADMIN 这类动态权限,不能按库表粒度授予,只能全局授予:GRANT session_variables_admin ON *.* TO 'webapp'@'10.20.30.%'。写成 ON mydb.* 会直接报 ERROR 1064。
动态权限生效还有两个隐性前提:
- 用户必须有
USAGE权限(新建用户自动带,但被REVOKE ALL清空后就没了) - 权限变更后,已有连接不继承新权限,必须重连;连接池需配
connection-init-sql="SET ROLE NONE; SET DEFAULT ROLE 'app_reader'"
生产环境别依赖 activate_all_roles_on_login 全局开关——它会让所有用户登录即激活全部已授角色,一旦角色里含高危动态权限(如 SYSTEM_VARIABLES_ADMIN),风险不可控。


















