mysql权限默认“未授予即拒绝”,grant select需先revoke冗余权限,按表级/数据库级精确授权,flush privileges非必需,须实测验证权限限制效果。

GRANT SELECT 时必须显式排除其他权限
MySQL 的权限体系默认是“白名单”机制,不赋予权限就等于禁止。但很多人误以为只执行 GRANT SELECT 就万事大吉,其实如果用户之前被授予过 UPDATE 或 DELETE(比如通过角色、旧账号复用、或 GRANT ALL PRIVILEGES),这些权限不会被自动清除。
正确做法是先确认并清理冗余权限:
- 查当前权限:
SHOW GRANTS FOR 'username'@'host'; - 若发现多余权限,必须显式回收:
REVOKE INSERT, UPDATE, DELETE, DROP, ALTER ON db_name.* FROM 'username'@'host'; - 再授予最小必要权限:
GRANT SELECT ON db_name.table_name TO 'username'@'host';
注意数据库级和表级授权的粒度差异
GRANT SELECT ON db_name.* 允许查该库下所有现有及未来新建的表;而 GRANT SELECT ON db_name.table_name 只针对单表。两者行为差异直接影响权限控制精度。
常见疏漏点:
- 用
db_name.*授权后,DBA 新增敏感表(如user_credentials)会自动对用户开放——这不是漏洞,是设计如此 - 若业务只要查几张固定表,优先用表级授权,避免权限蔓延
- MySQL 8.0+ 支持列级权限(
GRANT SELECT(col1, col2) ON ...),但仅限 SELECT,且不能和表级 SELECT 混用(会覆盖)
FLUSH PRIVILEGES 不是每次都要执行
执行 GRANT 或 REVOKE 后,MySQL 会自动重载权限缓存,FLUSH PRIVILEGES 完全不需要——除非你手动修改了 mysql.user 表(不推荐)。
滥用 FLUSH PRIVILEGES 的后果:
- 在高并发场景下可能引发短暂的权限校验延迟(因锁表)
- 掩盖真正的问题:比如忘记
REVOKE导致权限残留,却误以为是缓存没刷新 - MySQL 5.7+ 对直接改系统表更严格,强制要求
FLUSH才生效,但这属于异常路径
验证权限是否真正受限最可靠的方式是模拟操作
别只信 SHOW GRANTS 输出,得真连上去试。用该用户登录后执行典型越权操作,观察错误信息是否符合预期:
-
INSERT INTO table_name VALUES (...);→ 应报错ERROR 1142 (42000): INSERT command denied to user -
DELETE FROM table_name LIMIT 1;→ 应报错ERROR 1142 (42000): DELETE command denied to user - 特别注意
DROP TABLE和TRUNCATE TABLE:后者本质是 DROP + CREATE,在只有 SELECT 权限时也会失败
权限配置容易在跨环境迁移(开发→测试→生产)时被覆盖,上线前务必在目标环境做真实连接验证。











