MySQL 中的权限层级是怎么划分的
MySQL 的权限不是扁平的,而是分层的:全局(
GRANT OPTION)、数据库级(
test.*)、表级(
test.users)、列级(
SELECT(name, email))、甚至存储过程/函数级。权限生效时,MySQL 会从最具体层级向上匹配,但**高一层级的拒绝(
DENY)不被支持**——只有显式
REVOKE或未授权才等效于“无权”。 新建用户默认没有任何权限,哪怕有
USAGE(仅登录能力)也得显式授予
mysql.user表只存全局权限;库/表级权限存在
mysql.db、
mysql.tables_priv等系统表中 使用
SHOW GRANTS FOR 'u'@'h'查看实际生效权限,比查系统表更可靠
创建用户时 host 部分写 % 还是 localhost 有啥区别
'user'@'%'允许该用户从任意 IP 连接(包括本机),而
'user'@'localhost'**仅匹配 Unix socket 或 TCP 到 127.0.0.1 的连接**,且在权限检查时优先级更高。这两者是完全独立的账号,可能密码不同、权限不同。 Linux 下用
mysql -u user默认走 socket,匹配
localhost;加
-h 127.0.0.1就走 TCP,匹配
%或
127.0.0.1不要盲目用
'user'@'%'配合强密码来替代
localhost账号——某些运维脚本或监控工具硬编码了
localhost连接方式 若需限制仅内网访问,用
'user'@'192.168.1.%'比
%更安全
GRANT 语句执行后为什么权限没立刻生效
多数情况下权限会立即生效,但有两个常见例外:
如果用户当前已有活跃连接,新授予权限**不会自动同步到该会话**,需断开重连或执行FLUSH PRIVILEGES(不推荐,仅当直改系统表后才需要) 若启用了
read_only=ON,非 super 用户无法执行
GRANT,会报错
ERROR 1290 (HY000): The MySQL server is running with the --read-only optionMySQL 8.0+ 引入角色(
ROLE),角色权限变更后,已激活该角色的会话也不会自动更新,需重新
SET ROLE
删除用户用 DROP USER 还是 DELETE FROM mysql.user
必须用
DROP USER 'u'@'h'。直接
DELETE FROM mysql.user不仅不刷新权限缓存,还会留下残缺状态:
DROP USER 'app_rw'@'10.10.%.%';
DROP USER自动清理
mysql.db、
mysql.tables_priv等关联权限记录 手动删
mysql.user行后,必须跟
FLUSH PRIVILEGES,否则下次重启可能因元数据不一致报错 MySQL 8.0+ 中,
DROP USER还会自动撤销该用户持有的所有角色(
REVOKE ROLE ... FROM) 权限系统真正复杂的地方不在语法,而在 host 匹配逻辑和会话缓存行为——这两个点线上出问题时最难排查。
