MySQL 用户权限控制的核心机制是什么
MySQL 的权限控制基于「用户账户 + 主机范围 + 权限粒度」三要素组合,不是单纯给某个用户名赋权,而是以
'username'@'host'为完整标识。比如
'appuser'@'192.168.1.100'和
'appuser'@'localhost'是两个完全独立的账户,权限互不影响。 权限存储在
mysql.user、
mysql.db、
mysql.tables_priv等系统表中,不建议直接 UPDATE,必须用
GRANT/
REVOKE操作并配合
FLUSH PRIVILEGES(仅在直接改表后需要) 所有权限检查按「精确匹配 → 模糊匹配 → 默认拒绝」顺序执行,没有隐式继承或通配回退 新建用户默认无任何权限,包括
USAGE(连接能力),必须显式授予
如何安全创建应用专用账号(非 root)
生产环境绝不能用
root连接业务应用。应为每个服务单独建账号,并限制来源 IP 或域名:
CREATE USER 'webapp'@'10.0.2.5' IDENTIFIED BY 'strong_pass_2024!';
GRANT SELECT, INSERT, UPDATE ON mydb.orders TO 'webapp'@'10.0.2.5';
GRANT SELECT ON mydb.products TO 'webapp'@'10.0.2.5';
FLUSH PRIVILEGES;必须指定具体主机,避免用
'webapp'@'%'(除非真需任意 IP 连接,且已通过防火墙严控) 不要授予
GRANT OPTION,否则该用户可转授权限 避免使用
ALL PRIVILEGES,哪怕只读也优先选
SELECT而非
SHOW DATABASES(后者会暴露库名) 密码必须含大小写字母+数字+符号,长度 ≥12;MySQL 8.0+ 推荐用
VALIDATE_PASSWORD插件强制策略
为什么 REVOKE 后权限没立即失效
常见现象:执行了
REVOKE DELETE ON mydb.* FROM 'devuser'@'localhost';,但应用仍能删数据。原因通常有: 用户实际登录的是另一个同名但主机不同的账户,例如应用连的是
'devuser'@'%',而你 revoke 的是
'devuser'@'localhost'权限缓存未刷新:MySQL 会缓存权限结果,尤其是高并发场景下,
REVOKE后需执行
FLUSH PRIVILEGES;(注意:仅当用
GRANT/REVOKE时一般不需要,但某些旧版本或特殊配置下可能卡住) 用户拥有更高层级权限:比如对
mydb有
ALL,又单独 revoke 了
DELETE,此时仍有效——MySQL 权限是“叠加生效”,不是“覆盖撤销”
MySQL 8.0+ 角色(ROLE)怎么用才不踩坑
角色适合管理多用户共性权限,但要注意:
角色本身不自动激活,用户登录后需手动SET ROLE role_name;或设为默认:
SET DEFAULT ROLE role_name TO 'user'@'host';角色不能嵌套(A 角色无法包含 B 角色),也不能被
REVOKE出权限再赋给另一个角色
SHOW GRANTS FOR CURRENT_USER不显示角色权限,得用
SHOW GRANTS FOR CURRENT_USER USING role_name;如果用
mysqldump备份,角色定义不会自动导出,需额外备份
mysql.role_edges和
mysql.default_roles表
权限模型看着简单,实际生效逻辑藏在 host 匹配、权限层级叠加、缓存刷新、角色激活多个环节里。最容易漏的是主机名写法(
'%' ≠ 'localhost')、忘记
FLUSH PRIVILEGES的触发条件、以及误以为
REVOKE是“覆盖操作”。
