用户只能建表不能建库的正确做法是:先创建数据库,再授予库级create权限(on app_db.),禁止全局grant create on .*;否则用户可执行create database。

只给用户 CREATE 权限但禁止 CREATE DATABASE
MySQL 的 CREATE 权限在全局(GRANT ... ON *.*)下会隐含允许创建数据库,这是最容易踩的坑。想让用户只能建表、不能建库,必须把权限粒度控制在数据库级别,且不授予任何全局 CREATE 权限。
- ✅ 正确做法:先创建目标数据库(如
app_db),再对用户授予该库下的CREATE、INSERT、SELECT等权限 - ❌ 错误做法:执行
GRANT CREATE ON *.* TO 'user'@'%'—— 这会让用户能执行CREATE DATABASE - ⚠️ 注意:
CREATE权限在库级作用域(ON app_db.*)仅允许建表/视图/存储过程等,不包含建库
用 GRANT 语句精确授权建表权限
用户需要在指定数据库中建表,只需授予该库下的 CREATE 和 ALTER(用于后续加字段),无需 CREATE TEMPORARY TABLES 或 INDEX(除非明确需要)。
CREATE DATABASE IF NOT EXISTS app_db; GRANT CREATE, ALTER, INSERT, SELECT, UPDATE, DELETE ON app_db.* TO 'dev_user'@'%' IDENTIFIED BY 'strong-pass-2024'; FLUSH PRIVILEGES;
-
app_db.*表示权限仅作用于app_db库内所有现有及未来表 - 不加
WITH GRANT OPTION,防止用户转授权限 - 如果用户还需建视图或存储过程,额外加
CREATE VIEW、CREATE ROUTINE
验证用户是否真不能建库
用该用户连接后执行 CREATE DATABASE test_db;,应明确报错:ERROR 1044 (42000): Access denied for user 'dev_user'@'%' to database 'test_db'。而建表操作应成功:
USE app_db; CREATE TABLE users (id INT PRIMARY KEY, name VARCHAR(50)); -- ✅ 成功
- 若建库没报错,说明之前误授了全局
CREATE或用户有root类高权限角色 - 检查权限实际生效情况:用
SHOW GRANTS FOR 'dev_user'@'%';查看当前有效授权 - 注意:MySQL 8.0+ 使用角色(ROLE)管理时,需确认角色本身未包含全局权限
生产环境建议禁用匿名用户与空密码
限制建库建表只是权限收紧的第一步。真实风险常来自弱口令或残留的 ''@'localhost' 匿名账户,它们可能拥有意外的高权限。
- 运行
SELECT User,Host,authentication_string FROM mysql.user WHERE User='';检查匿名用户 - 删除无用账户:
DROP USER ''@'localhost'; - 确保
mysql.user表中没有Super_priv或Grant_priv为Y的非运维账户
权限收缩不是一次性配置,而是每次新建用户都得重审授权范围——尤其当 DBA 习惯性复制旧 GRANT 语句时,很容易把 ON *.* 带进去。










