MySQL权限安全的核心是限制主机、最小化授权、分层隔离:必须显式指定host(如'appuser'@'localhost'),禁用'%'通配;GRANT须精确到库表级,禁用ALL PRIVILEGES;SHOW GRANTS查真实权限,权限检查按四级叠加且拒绝优先;业务权限需在应用层实现WHERE过滤,与数据库权限分离。

GRANT 和 DROP USER 是 MySQL 权限管理最直接的入口,但真正安全的权限控制不是靠“给全权”或“删账号”实现的,而是靠明确限制主机、最小化授权、分层隔离。
创建用户时必须指定 host,不能省略
MySQL 把 'user'@'host' 当作一个完整身份标识,'appuser' 和 'appuser'@'localhost' 是两个不同用户。省略 @'host' 会默认变成 'appuser'@'%',即允许任意 IP 连接——生产环境基本等于裸奔。
- 只允许本机应用连接:用
'appuser'@'localhost' - 只允许内网某段访问:用
'appuser'@'192.168.10.%' - 绝对避免写成
CREATE USER 'appuser' IDENTIFIED BY 'pwd';(隐含@'%') -
host字段在mysql.user表里查得到,SELECT host,user FROM mysql.user;可验证
GRANT 授权必须精确到库表,别碰 ALL PRIVILEGES
业务账号几乎不需要 DROP、ALTER、CREATE 或跨库权限。给 ALL PRIVILEGES ON *.* 就是把数据库交出去了,哪怕只是测试环境也容易被误操作波及。
- 常见安全组合:
GRANT SELECT, INSERT, UPDATE ON myapp_db.* TO 'appuser'@'localhost'; - 只读账号加
SELECT即可,别多给USAGE(它只是“能连上”,不带任何数据权限) - 如果应用只读某个视图,就只授
SELECT给那个视图,而不是整张基表 - 执行完
GRANT后不用FLUSH PRIVILEGES——GRANT自动刷新,只有改mysql.user表直写才需要它
用 SHOW GRANTS 查真实权限,别信 SELECT * FROM mysql.user
mysql.user 表里的 _priv 字段(如 Select_priv)只反映全局级权限,而实际生效的是“全局 → 数据库 → 表 → 列”四级叠加结果。直接查这张表容易误判。
- 看当前会话权限:
SHOW GRANTS; - 看指定用户权限:
SHOW GRANTS FOR 'appuser'@'localhost'; -
current_user()返回 MySQL 实际匹配的账号(比如你用appuser登录,但匹配到的是appuser@%),这才是权限校验依据 - 权限检查顺序是:先找最具体的(库+表),没命中再往上走;只要某一级拒绝(
REVOKE),就直接 deny,不继续匹配
MySQL 账户权限 ≠ 业务权限,别混用
你在 users 表里设计的“编辑订单”权限,和 MySQL 的 UPDATE ON orders 是两回事。前者由应用逻辑控制,后者是数据库连接底线。
- MySQL 用户权限管三件事:能不能连进来、能看哪些库、能对哪些对象执行哪些 SQL 动词
- 业务权限(比如“只能改自己创建的订单”)必须在应用层做 WHERE 校验,不能靠数据库约束
- 即使用了 RBAC 表结构,也要确保连接数据库的账号本身只拥有对应库的最小操作集
- root 账号绝不用于应用连接;每个服务应有独立账号,密码定期轮换
真正卡住风险的点不在“怎么加权限”,而在“怎么限制连接来源”和“权限是否随业务演进及时回收”。一个被遗忘的 'backup_user'@'%',比十个配置错误的业务权限更危险。


















