必须先create user再grant授权,不能在create user中指定数据库权限;需用grant select,insert,update on myapp_db.明确授予权限,并避免grant all on .*以确保库级隔离。

创建用户时指定数据库权限范围
MySQL 的用户权限是按层级授予的,直接在 CREATE USER 语句里无法限定“只允许访问某个库”——这个限制必须靠后续的 GRANT 控制。常见误区是以为建用户时加个 FOR 'db_name' 就能锁定库,其实 MySQL 不支持这种语法。
- 先用
CREATE USER 'app_user'@'localhost' IDENTIFIED BY 'strong_pass123';创建用户(注意主机名要匹配实际连接来源,比如应用服务器 IP 或%) - 再用
GRANT SELECT, INSERT, UPDATE ON `myapp_db`.* TO 'app_user'@'localhost';明确授权到具体库的表级操作 - 执行
FLUSH PRIVILEGES;生效(仅在修改mysql.user表直改时才必需;GRANT自动刷新)
为什么不能只给 DATABASE 权限?
GRANT USAGE ON `myapp_db`.* 是最低权限,但不等于“只允许访问该库”——它只是不授任何操作权。真正起隔离作用的是“没被显式授予的权限默认拒绝”。所以关键不是“给什么”,而是“不给什么”:
- 不要执行
GRANT ALL ON *.*或GRANT ALL ON `*`.*,这会绕过库级隔离 - 避免
GRANT ... ON `*`.`*`,它覆盖所有库,包括mysql、information_schema - 如果用户需要查系统表(比如
SHOW TABLES),MySQL 8.0+ 默认允许访问information_schema,无需额外授权;旧版本若报错,可单独加GRANT SELECT ON `information_schema`.*
验证权限是否生效
别只信 SHOW GRANTS FOR 'app_user'@'localhost'; 的输出,得实测连接后行为:
MySQL 9.6.0是面向Linux平台的2026年创新版本,核心架构迎来重大革新。其将外键约束与级联操作从InnoDB引擎层上移至SQL层,确保所有数据变更均被完整记录至Binlog,彻底解决了CDC(变更数据捕获)与主从复制中的数据不一致难题。此外,该版本引入container_aware启动选项以原生适配容器环境,并对审计日志进行了组件化重构,为追求极致数据一致性与云原生体验的开发者提供了全新选择。
- 用
mysql -u app_user -p -D myapp_db登录,执行SELECT * FROM users;应成功 - 切换库:
USE other_db;会报错ERROR 1044 (42000): Access denied for user 'app_user'@'localhost' to database 'other_db' - 尝试跨库查询:
SELECT * FROM other_db.products;同样报错,哪怕目标表存在
容易被忽略的权限细节
有些操作看似跟库无关,实则隐含跨库依赖:
-
CREATE TEMPORARY TABLE需要CREATE TEMPORARY TABLES权限,且该权限是全局的(ON *.*),不能限定到单库 - 使用存储过程或函数时,调用者需对过程所在库有
EXECUTE权限,且过程内部若访问其他库的表,权限检查发生在执行时而非定义时 - MySQL 8.0 的角色(
CREATE ROLE)可以封装权限组合,但角色本身仍需通过GRANT绑定到用户,隔离逻辑不变
最稳妥的做法:始终用最小权限原则,只授 ON `target_db`.*,并定期用 SELECT user, host, db FROM mysql.db WHERE user = 'app_user'; 检查授权记录是否意外残留旧条目。










