PHP 7.4及更早版本直连MySQL 8.0失败的核心原因是caching_sha2_password认证插件不兼容,需执行ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'pwd'并FLUSH PRIVILEGES。

PHP 7.4 及更早版本直连 MySQL 8.0 默认失败,核心卡在认证插件不兼容,不是扩展选错,而是驱动层没对上。
MySQL 8.0 的 caching_sha2_password 让旧版 PHP 直接报错
MySQL 8.0 默认用 caching_sha2_password 插件做用户认证,而 PHP 7.4 及更早版本的 mysqlnd 驱动(尤其是 Windows 下预编译包)默认不支持它。现象很典型:
- 错误信息是
Authentication plugin 'caching_sha2_password' cannot be loaded或Client does not support authentication protocol -
mysqli_connect()和PDO::__construct()都会挂,跟写法无关 - 即使配置了正确的 host、port、user、pass,连接也卡在握手阶段
这不是代码问题,是底层 C API 层的认证能力缺失。
服务端降级是最稳的解法
如果你能改 MySQL 配置或用户权限,优先走服务端适配,省去客户端各种补丁:
- 新建用户时强制指定旧插件:
CREATE USER 'app_user'@'%' IDENTIFIED WITH mysql_native_password BY 'secret123'; - 修改已有用户:
ALTER USER 'app_user'@'%' IDENTIFIED WITH mysql_native_password BY 'secret123'; - 全局改默认插件(不推荐生产环境):
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'xxx';
执行完记得 FLUSH PRIVILEGES;。这样 PHP 无论用 mysqli 还是 PDO 都能直连,无需改任何 PHP 代码。
客户端启用 mysqlnd 并绕过 SSL 是次选方案
如果无法动服务端,就得确认 PHP 底层用的是 mysqlnd(不是已淘汰的 libmysql),并在连接时显式压制认证和 SSL 干扰:
- 检查是否为
mysqlnd:phpinfo()中搜mysqlnd,或运行var_dump(mysqli_get_client_info());看输出是否含mysqlnd - PDO 连接加选项:
['PDO::MYSQL_ATTR_SSL_MODE' => PDO::SSL_DISABLED, 'PDO::ATTR_ERRMODE' => PDO::ERRMODE_EXCEPTION] - mysqli 面向对象方式可尝试加前缀:
new mysqli('p:localhost', ...)(p:启用持久连接,部分版本会触发更宽松的握手逻辑) - 但注意:禁用 SSL 在公网环境有风险,仅限内网调试用
PHP 8.0+ 原生支持 caching_sha2_password,所以升级 PHP 版本本身也是根治方案——不过得同步验证框架和扩展兼容性。
MySQL 5.7 和 8.0 对 PHP 扩展没有功能差异
只要认证插件对得上,PDO 和 mysqli 在这两个版本间的行为完全一致。所谓“MySQLi 更适配 8.0”是误解:
- 两者都依赖同一套底层驱动(
mysqlnd),不因扩展名不同而获得额外协议支持 - MySQL 8.0 的新特性(如角色管理、JSON 表达式优化)需靠 SQL 语句调用,与 PHP 扩展无关
-
mysqli::get_client_info()和PDO::getAttribute(PDO::ATTR_CLIENT_VERSION)返回的都是驱动版本,不是 MySQL 服务端版本
真正容易被忽略的是字符集初始化——MySQL 8.0 默认 utf8mb4_0900_as_cs 排序规则,但 PHP 连接时若不显式设 SET NAMES utf8mb4,可能触发隐式转换或报错,这个细节比扩展选型影响更大。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











