CREATE USER 语句必须指定 IDENTIFIED BY 吗?
MySQL 8.0+ 默认启用
validate_password插件,
CREATE USER时若不带密码,会报错
ERROR 1819 (HY000): Your password does not satisfy the current policy requirements。即使策略宽松,也建议显式设密——空密码或跳过认证(如
auth_socket)仅适用于本地调试,生产环境禁用。
正确写法:
CREATE USER 'app_user'@'192.168.1.%' IDENTIFIED BY 'StrongPass!2024';
常见错误:
漏写@'host',导致默认为
@'%',权限范围过大 用双引号包裹用户名或主机名(MySQL 要求单引号) 密码含特殊字符但未用单引号包裹,引发 SQL 解析错误
GRANT 之后为什么 SELECT 还报 Access denied?
权限生效需两步:授权 + 刷新权限缓存。MySQL 不自动重载权限表,
GRANT只写入
mysql.user等系统表,连接线程仍用旧权限缓存。
必须执行:
FLUSH PRIVILEGES;
但更推荐的做法是:用
GRANT后直接新建连接验证,而非依赖
FLUSH——因为
GRANT本身在多数版本中已隐式刷新(MySQL 5.7.6+),
FLUSH PRIVILEGES实际只对手动修改系统表有效。真正容易被忽略的是: 用户 host 不匹配:比如创建的是
'app_user'@'192.168.1.%',但应用连的是
localhost(等价于
127.0.0.1或 Unix socket),需额外授权
'app_user'@'localhost'权限作用域错误:对库级权限(如
SELECT ON mydb.*)误授给
mydb.table1(表级),或漏掉
USAGE基础权限
如何最小化授权又满足 Web 应用需求?
Web 应用通常只需 CRUD,禁用 DDL 和管理权限。避免使用
GRANT ALL PRIVILEGES,尤其不要对
*全局授权。
典型安全授权示例:
GRANT SELECT, INSERT, UPDATE, DELETE ON `myapp_db`.* TO 'app_user'@'192.168.1.%'; GRANT USAGE ON *.* TO 'app_user'@'192.168.1.%';
关键点:
USAGE是空权限占位符,允许用户连接但无任何操作权,配合具体库权限使用更清晰 数据库名用反引号包裹,防止库名含短横线(如
my-app-db)导致语法错误 不授
INDEX、
CREATE TEMPORARY TABLES等非必要权限,除非 ORM 明确需要 若应用用连接池且复用长连接,改权限后需重启连接池或等待连接超时重建
删除用户后权限还残留?
用
DROP USER 'user'@'host'才彻底清除用户记录和权限;仅
DELETE FROM mysql.user不行——权限表之间有关联(如
mysql.db、
mysql.tables_priv),手动删会留下脏数据,下次
FLUSH PRIVILEGES可能报错或行为异常。
安全删除流程:
DROP USER 'app_user'@'192.168.1.%';
验证是否清空:
SELECT User, Host FROM mysql.user WHERE User = 'app_user';
注意:
DROP USER在 MySQL 5.7+ 支持一次删多个,如
DROP USER 'u1'@'h1', 'u2'@'h2';低版本需分多次执行。另外,如果用户正在连接,MySQL 不会阻止删除,但其活跃会话仍保持权限直到断开——这点常被忽视。
