mysqli_connect报access denied的真实原因是user@host组合不匹配或认证插件不兼容:mysql严格按'user'@'host'二元组校验权限,'localhost'与'127.0.0.1'视为不同主机,且mysql 8.0+默认caching_sha2_password插件与旧php客户端不兼容。

mysqli_connect 报 Access denied 的真实原因不是密码错
错误信息里 Access denied for user 'xxx'@'localhost' 的 'xxx'@'localhost' 就是关键线索:MySQL 拒绝的是这个特定的 user@host 组合,而不是泛泛地说“密码不对”。常见现象是改了十遍密码还是报错,因为问题根本不在密码——而是你 PHP 代码连的是 'localhost',但 MySQL 里压根没有 'xxx'@'localhost' 这条记录,只有 'xxx'@'127.0.0.1' 或 'xxx'@'%'。这两者在权限表里完全独立,互不替代。
-
localhost在 MySQL 中强制走 Unix socket,只匹配user@'localhost'记录 -
127.0.0.1强制走 TCP,匹配user@'127.0.0.1'或user@'%' - 用命令行验证最准:
mysql -u xxx -p -h 127.0.0.1(加-h才走 TCP) - 进库后立刻执行
SELECT USER(), CURRENT_USER();—— 前者是你声明的,后者才是 MySQL 实际查到的权限记录,两者不同就说明 host 不匹配
MySQL 8.0+ 的 caching_sha2_password 插件导致静默失败
PHP 脚本连 MySQL 8.0+ 时,即使用户名、密码、host 全对,也可能报 Access denied。这不是权限问题,是协议不兼容:caching_sha2_password 是 MySQL 8.0 默认认证插件,但 PHP 7.4 之前版本或未启用 mysqlnd 驱动的环境无法识别它,直接拒连,错误还伪装成密码错。
- 先确认插件类型:
SELECT user, host, plugin FROM mysql.user WHERE user = 'xxx'; - 若
plugin是caching_sha2_password,且你没法升级 PHP,就切回兼容模式:ALTER USER 'xxx'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your_pass'; - 必须指定
@'localhost'(或对应 host),不能只写'xxx',否则改的是另一条记录 - 执行完
FLUSH PRIVILEGES;生效 - 检查 PHP 是否启用了
mysqlnd:运行phpinfo(),搜mysqlnd;没启用就换扩展或重装 PHP
mysqli_connect() 返回 false 后直接调 query() 必然报错
错误日志里紧跟着出现 Fatal error: Call to a member function query() on bool,说明你在 mysqli_connect() 失败返回 false 后,没做判断就直接调了 $conn->query()。这不是数据库问题,是 PHP 代码健壮性缺失。
- 必须显式检查连接结果:
if (!$conn) { die('连接失败: ' . mysqli_connect_error()); } - 别把端口混进主机名,比如
'localhost:3306'是错的;正确写法是分开传参:mysqli_connect('127.0.0.1', 'user', 'pass', 'db', 3306) - 注意
localhost和127.0.0.1的行为差异:前者不走端口参数,后者才需要第 5 个端口参数 - Docker 或 phpStudy 等集成环境里,
localhost往往指向宿主机,而 MySQL 容器实际监听的是容器内网 IP,此时应填服务名(如'mysql')或宿主机 IP(如'192.168.1.100'),而非'localhost'
创建用户和授权时 host 字段必须精确一致
很多人执行 CREATE USER 'myapp' IDENTIFIED BY 'pwd';,以为默认 host 是 '%' 就万事大吉,结果 PHP 连 'localhost' 还是失败。MySQL 的权限校验是严格三元组匹配:user + host + plugin 缺一不可。
- 建用户必须显式写 host:
CREATE USER 'myapp'@'localhost' IDENTIFIED BY 'pwd'; - 授权也必须用相同 host:
GRANT ALL PRIVILEGES ON `mydb`.* TO 'myapp'@'localhost'; - 如果 PHP 运行在 Docker 宿主机,实际来源 IP 可能是
'172.17.0.1'或'192.168.x.x',就得建'myapp'@'172.17.0.1'或放宽为'myapp'@'%'(仅开发环境) - 授
CREATE权限才能建库:GRANT CREATE ON *.* TO 'myapp'@'localhost';,普通SELECT权限不够 - 用
SHOW GRANTS FOR 'myapp'@'localhost';确认权限已生效,别只信GRANT语句执行成功
真正卡住人的地方,往往不是某一步做错了,而是多个条件叠加:比如你用了 MySQL 8.0,默认插件不兼容,同时用户又只建在 @'127.0.0.1',而 PHP 却连 'localhost',再配上没检查 mysqli_connect() 返回值——三个坑叠在一起,单看错误信息根本看不出根源。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











