shutdown是全局权限,必须显式指定on *.*,且需执行flush privileges生效;常见失败原因包括host不匹配、用户不存在、未刷新权限表。

不能直接用 GRANT SHUTDOWN 就完事——漏掉 ON *.* 或没执行 FLUSH PRIVILEGES,权限一定不生效。
为什么 GRANT SHUTDOWN ON mydb.* 会报错?
因为 SHUTDOWN 是全局管理权限,只允许作用于整个实例,语法上强制要求范围是 *.*。MySQL 会立刻拒绝任何带数据库名或表名的写法:
-
GRANT SHUTDOWN ON testdb.* TO 'user'@'localhost'→ 报错ERROR 1221 (HY000): Incorrect usage of DBA or GLOBAL privileges -
GRANT SHUTDOWN TO 'user'@'localhost'(省略ON)→ 实际等价于ON *.*,但属于隐式写法,不推荐;显式写出更安全、可读性更强 - 只要出现
db.*或db.table这类限定,就不是SHUTDOWN的合法作用域
授予权限后用户仍被拒绝执行 SHUTDOWN?检查这三点
常见现象:用户能正常连接 MySQL,但一执行 SHUTDOWN 就提示 ERROR 1045 (28000): Access denied。问题往往出在以下环节:
- 授权后没运行
FLUSH PRIVILEGES:MySQL 不会自动重载权限表,必须手动刷新才能让新权限进入内存 - 主机名不匹配:比如授权的是
'adminctl'@'localhost',但用户用-h 127.0.0.1连接,MySQL 会当作'adminctl'@'127.0.0.1'处理,而这个账号根本不存在 - 用户不存在就直接授予权限:MySQL 5.7+ 默认不允许对不存在的用户执行
GRANT,会报错ERROR 1133 (42000): Can't find any matching row in the user table;得先CREATE USER再GRANT
用 mysqladmin shutdown 需要额外注意什么?
即使 SHUTDOWN 权限已正确授予,mysqladmin 仍可能失败,原因很具体:
- 连接方式必须和授权 host 一致:授权
'adminctl'@'localhost',就该用 socket 文件连接(-S /tmp/mysql.sock),而不是-h localhost;后者经 DNS 解析后可能变成127.0.0.1,触发 host 不匹配 - MySQL 8.0+ 默认禁用命令行传密码:
mysqladmin -u adminctl -p shutdown会提示警告,且可能被审计拦截;建议改用配置文件~/.my.cnf存凭证,避免泄露 -
mysqladmin调用的是服务端SHUTDOWN命令,它不依赖客户端是否支持SHUTDOWN语句,但完全受制于服务端权限校验逻辑
不需要给其他权限,SHUTDOWN 是独立权限
有人习惯性顺手加 RELOAD 或 SUPER,其实没必要:
-
SHUTDOWN不依赖RELOAD(后者用于FLUSH LOGS等操作) - 也不需要
SUPER(MySQL 5.7+ 已拆分管理权限,SHUTDOWN自成一类) - 过度授权反而增加风险:比如
RELOAD允许刷日志、重载配置,SUPER可 kill 线程或修改只读模式,都和关机无直接关系
真正容易被忽略的是 host 匹配和 FLUSH PRIVILEGES 的时机——这两个点卡住,再正确的 SQL 也白写。











