create user语句必须显式指定@host部分,因mysql用户由username@host共同唯一标识;漏写会导致创建无法连接的账号,且本地socket连接实际匹配'localhost'而非默认'%'。

create user 语句必须指定@host部分
MySQL 的用户身份由 username@host 共同决定,漏写 @'localhost' 或 @'%' 会导致创建出一个你根本连不上的账号。比如只写 CREATE USER 'alice',MySQL 默认补成 'alice'@'%',但如果你本地用的是 socket 连接(常见于 macOS/Linux 的 homebrew 或官方 dmg 安装),实际走的是 'alice'@'localhost' —— 这俩是完全不同的用户,权限不互通。
实操建议:
- 明确连接来源:本地开发用
'alice'@'localhost',远程应用用'alice'@'192.168.1.%'或'alice'@'%'(后者慎用) - 不要依赖默认 host 补全,始终显式写出
@部分 - 创建后立刻用
SELECT User, Host FROM mysql.user;确认记录是否符合预期
密码必须用 IDENTIFIED BY,不能直接 INSERT 到 mysql.user
有人看到 mysql.user 表里有 authentication_string 字段,就想绕过 CREATE USER 直接 INSERT,这是错的。5.7+ 版本密码哈希逻辑和插件绑定(如 caching_sha2_password),手动插入未加密或格式错误的字符串会导致登录时报错 ERROR 1045 (28000): Access denied,且无法通过 SET PASSWORD 修复。
实操建议:
- 一律用
CREATE USER 'u'@'h' IDENTIFIED BY 'pwd';创建带密码用户 - 如果要用特定认证插件(比如老应用不支持 sha2),加
IDENTIFIED WITH mysql_native_password BY 'pwd' - 避免在命令行中明文写密码:用
CREATE USER 'u'@'h' IDENTIFIED BY ''; SET PASSWORD FOR 'u'@'h' = 'pwd';分两步(注意第二步需有UPDATE权限)
CREATE USER 不赋予任何权限,连 SELECT 都不行
CREATE USER 只建账号,不给权限。新用户首次登录后执行任何 SQL 都会报 ERROR 1142 (42000): SELECT command denied to user。这不是密码错,也不是连接问题,是权限空集导致的。
实操建议:
- 创建后立刻用
GRANT赋权,例如GRANT SELECT, INSERT ON mydb.* TO 'u'@'h'; - 避免
GRANT ALL PRIVILEGES给生产账号;最小权限原则下,先给USAGE(仅登录),再按需追加 - 执行
GRANT后必须跟FLUSH PRIVILEGES;吗?不用。MySQL 8.0+ 和大多数 5.7 场景下,GRANT自动刷新权限缓存;只有直接改表才需要手动刷
MySQL 8.0 默认认证插件变了,客户端可能连不上
MySQL 8.0 默认用 caching_sha2_password,而老版本 MySQL 客户端、某些 ORM(如旧版 Django)、甚至 Navicat 12 以下版本不支持该插件,会报 Client does not support authentication protocol requested by server。
实操建议:
- 新建用户时指定兼容插件:
CREATE USER 'u'@'h' IDENTIFIED WITH mysql_native_password BY 'pwd'; - 或者全局降级(不推荐):
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'xxx'; - 检查当前用户用的什么插件:
SELECT User, Host, plugin FROM mysql.user WHERE User = 'u';
真正麻烦的不是创建,是后续所有依赖这个账号的服务都得同步适配——插件类型一旦定下,改起来比换密码还费劲。











