MySQL的权限存储在mysql系统数据库的user、db、tables_priv、columns_priv、procs_priv和proxies_priv表中,其中user表控制全局权限,db表控制数据库级权限,其余细化到表、列或存储过程。

MySQL 的权限存储在哪张表里
MySQL 的 ACL(Access Control List)信息全部存放在 mysql 系统数据库的几张核心表中,不是内存结构或配置文件。主要涉及:user、db、tables_priv、columns_priv、procs_priv 和 proxies_priv。
其中最常用的是:
-
user:控制全局级别权限(如SELECT、CREATE USER)和连接参数(如max_connections) -
db:控制某个数据库级别的权限(如对myapp库的INSERT) -
tables_priv和columns_priv:细化到表或列的权限,实际生产中极少手动操作,多通过GRANT语句间接写入
直接 UPDATE 这些表不会立即生效——必须执行 FLUSH PRIVILEGES 才能重载,否则新权限不被识别。
GRANT 和 INSERT INTO mysql.user 的区别
用 GRANT 创建用户并赋权,是 MySQL 推荐且安全的方式;而直接 INSERT INTO mysql.user 是绕过校验的“硬写”,容易出错。
关键差异:
-
GRANT会自动哈希密码(如果使用IDENTIFIED BY)、检查语法、填充默认权限字段(如ssl_type、account_locked),并隐式触发权限重载 - 手动
INSERT必须自己设置authentication_string(不是password字段,5.7+ 已废弃)、plugin(通常是caching_sha2_password或mysql_native_password),漏掉account_locked或password_expired可能导致用户无法登录 -
GRANT ... ON *.*写入user表;GRANT ... ON db.*写入db表;但直接INSERT不会自动关联db表,权限粒度会错位
例如,以下语句看似等价,实则风险不同:
GRANT SELECT ON mydb.* TO 'appuser'@'10.0.1.%' IDENTIFIED BY 'pwd123';
vs
INSERT INTO mysql.user (Host, User, authentication_string, plugin) VALUES ('10.0.1.%', 'appuser', PASSWORD('pwd123'), 'mysql_native_password');后者没设 Select_priv = 'Y',也没插入 db 表记录,用户创建成功但无任何权限。
Modoer 是一款以本地分享,多功能的点评网站管理系统。采用 PHP+MYSQL 开发设计,开放全部源代码。因具有非凡的访问速度和卓越的负载能力而深受国内外朋友的喜爱,不局限于商铺类点评,真正实现了多类型的点评,可以让您的网站点评任何事与物,同时增加产品模块,也更好的网站产品在网站上展示。Modoer点评系统 2.5 Build 20110710更新列表1.同步 旗舰版系统框架2.增加 限制图片
权限生效顺序与拒绝优先级
MySQL 权限按层级叠加,但“拒绝”(DENY)在 8.0+ 才支持,且只在企业版或 8.0.16+ 社区版通过 REVOKE + WITH ADMIN OPTION 间接体现;标准社区版没有显式 DENY 机制。
权限判断逻辑是“匹配最长 Host/User + 最高粒度”,顺序固定为:
- 先查
user表(全局)→ 匹配Host和User,满足则用该行权限 - 若全局无匹配,再查
db表 → 要求Host、User、Db全部匹配 - 再往下是
tables_priv、columns_priv,逐级细化
注意:user 表中某权限字段为 'N',不代表“拒绝”,只是“未授予”。MySQL 没有 deny-by-default 模式,所有未显式授予的权限默认不可用。
一个常见陷阱:user 表里 Select_priv = 'Y',但 db 表里同用户对某库 Select_priv = 'N' —— 实际仍可查(因为全局权限覆盖库级)。只有当全局为 'N',才继续下探。
FLUSH PRIVILEGES 什么时候必须执行
仅在**直接修改 mysql 系统表**后才需要 FLUSH PRIVILEGES;用 GRANT、CREATE USER、DROP USER 等 DDL 语句操作时,MySQL 自动重载权限缓存,无需手动刷新。
误用 FLUSH PRIVILEGES 的后果:
- 它强制重载全部权限数据,对高并发实例可能造成短暂锁表(尤其是
user表) - 如果此时系统表有损坏或格式错误(比如
authentication_string值非法),会导致整个权限系统不可用,连root都可能无法登录 - 在 MySQL 8.0+,部分字段(如
password_last_changed)由内部机制维护,手动FLUSH可能干扰其状态
所以,除非你明确改了 mysql.user 或 mysql.db 的行,否则不要碰 FLUSH PRIVILEGES。很多线上故障就源于运维脚本里无脑加这一句。









