表级权限必须写成 db.table
,不能用 db.*
这是最常踩的坑:一写
GRANT SELECT ON mydb.* TO 'u'@'h',你以为只给了某库下“所有表”的权限,其实这是数据库级权限,不是表级。MySQL 里真正的表级授权,
ON后面必须精确到单张表,比如
mydb.users或
mydb.orders。 正确写法:
GRANT SELECT, INSERT ON mydb.logs TO 'logger'@'localhost'错误写法:
GRANT SELECT ON mydb.* TO 'logger'@'localhost'(这是库级) 如果真要控制多张表,得一条一条写,或改用角色(MySQL 8.0+)批量管理
列级权限会自动收窄范围,不是叠加
你给用户授了全表
SELECT,再补一句
GRANT SELECT(name, email) ON mydb.users,结果不是“能查全表 + 额外强调两个字段”,而是直接变成“只能查 name 和 email”——其他字段访问会被拒绝。 列级
SELECT、
INSERT、
UPDATE有效,但
DELETE不支持列级
UPDATE (status)权限下,哪怕只改 status 字段,WHERE 条件里用了未授权的
id列,也会报错 撤销时也得对齐粒度:列级授的权,必须用列级
REVOKE SELECT(name, email) ON mydb.users才能撤掉
权限变更后老连接不生效,别被“测试没反应”骗了
MySQL 把权限缓存在服务端内存里,新连接会读最新配置,但已建立的连接不会自动刷新。你
GRANT完立刻用同一个客户端去试
SELECT,很可能还是报错——不是权限没设对,是连接太“懒”。 开发/测试阶段建议每次改完权限后,断开重连再验证 生产环境不要依赖
FLUSH PRIVILEGES(MySQL 8.0+ 的
GRANT默认已隐式刷新),但老连接仍需重连 注意用户标识的精确性:
'app'@'192.168.1.%'和
'app'@'%'是两个账号,权限得分别配
高危权限(DROP
、ALTER
)要单独评估,别混在常规授权里
很多团队图省事,直接
GRANT SELECT, INSERT, UPDATE, DELETE, ALTER ON ...,结果应用出 Bug 时,一个误操作就把表结构改崩了,甚至删表都拦不住。
DROP建议完全禁用,删表应走 DBA 流程或运维平台
ALTER只给 DBA 或迁移工具账号,业务应用账号通常不需要 如果真需要结构变更能力,可临时授权 + 限时回收,而不是长期开着 已有全局或库级
ALL权限的用户,
REVOKE表级权限无效——得先收回上层权限,再精细授予
实际配置时,最容易漏的是主机名匹配和连接复用问题;权限看似设对了,但因为用户标识不一致或连接没重连,一直卡在“明明写了却没效”的状态。
