MySQL权限到底分几级?不是“有无权限”,而是“在哪生效”
MySQL权限不是扁平的“能/不能”二选一,而是严格按作用域分层生效:全局 → 数据库 → 表 → 列 → 存储过程/函数。每一层权限都存在对应的系统表(
mysql.user、
mysql.db、
mysql.tables_priv等),MySQL启动时加载进内存,**权限检查是逐层匹配、取交集而非叠加**——比如用户在
user表有
SELECT全局权,但在
db表被显式拒绝该库的
SELECT,那最终就查不了这个库。
全局权限(*.*)能干啥?哪些操作必须它?
全局权限写在
mysql.user表里,用
GRANT ... ON *.*授予。它们不针对具体数据库,而是管理类操作的“入场券”:
PROCESS:执行
SHOW PROCESSLIST,查别人连接和正在跑的SQL——没它,连自己连接都看不到完整信息
SUPER:杀连接(
KILL)、切主从(
CHANGE MASTER TO)、动态改变量(
SET GLOBAL)——开发环境常误开,生产务必收敛
REPLICATION SLAVE:仅用于从库拉binlog,主库账号绝不能给这个权限
SHUTDOWN:执行
mysqladmin shutdown——等同于直接关实例,几乎不该分配
FILE:读写服务器文件(
LOAD DATA INFILE/
SELECT ... INTO OUTFILE)——可读
/etc/passwd,高危
表级和列级权限怎么配才不踩坑?
表级(
GRANT SELECT ON db.tbl)和列级(
GRANT UPDATE(col1) ON db.tbl)权限存于
mysql.tables_priv和
mysql.columns_priv,但实际使用中容易掉进两个坑: 列级权限只对
UPDATE/
SELECT/
INSERT生效,
DELETE或
DROP这类行/对象级操作,**不认列权限**——哪怕你只授了
col1的
UPDATE,用户删整行照样成功 如果用户同时有全局
SELECT和某张表的
SELECT,MySQL不会报错,但
SHOW GRANTS只显示最高层级的授权语句(即
*.*),**你根本看不出他其实被单独限制过某张表**——排查越权时得手动查
mysql.db和
mysql.tables_priv
ALTER表结构需要
CREATE+
INSERT配合,单给
ALTER无效;
TRUNCATE TABLE本质是
DROP+
CREATE,所以依赖
DROP权限,不是
DELETE
角色(Role)真能替代手工赋权吗?
MySQL 8.0+原生支持
CREATE ROLE,但要注意:角色本身不登录,只是权限容器,必须
GRANT role_name TO user才能生效。它的价值不在“省事”,而在解耦: 运维组统一维护
role_readonly,所有只读账号都
GRANT它,删权限只需改角色,不用遍历每个用户 但
REVOKE角色权限后,用户当前会话仍保留旧权限,**必须执行
SET ROLE DEFAULT或重新登录才刷新**——自动化脚本里漏这步,权限回收就失效 5.7及更早版本没有角色,只能靠
mysql.proxies_priv模拟,但那是“代理用户”机制,和角色语义不同,别混用 权限体系的核心不是“我能给多少”,而是“我在哪一层做了什么”。
mysql.user表一旦写错
Super_priv='Y',整个实例就暴露;而
mysql.db里一个
Select_priv='N'可能让应用查不到数据却报错模糊。查权限永远从
SHOW GRANTS FOR 'u'@'h'起步,再顺藤摸到对应系统表,别猜。
