应先查看PDOException的message字段获取真实错误:如[2002]表示服务未启动或网络不通,[1045]为认证失败,[2002]加“No such file”则指向socket路径问题;再针对性排查host、port、env加载及MySQL 8.0认证插件等。

报错不是配置写错了就是 PDO 根本没连上,先看 PDOException 的 message 字段,再动手改配置或重启服务。
怎么看 PDOException 的真实错误信息
ThinkPHP 不会自己造错,它只是把 PDO 抛出来的异常原样往上扔。关键就藏在 message 里:
-
"SQLSTATE[HY000] [2002] Connection refused"→ MySQL 没启动,或 host/port 对不上 -
"SQLSTATE[HY000] [1045] Access denied for user"→ 用户名密码错,或该用户不允许从当前 host 连入(比如数据库里是'user'@'localhost',但 PHP 跑在 Docker 容器里) -
"SQLSTATE[HY000] [2002] No such file or directory"→ 配置写了localhost,但 MySQL 没开 socket,或路径不对(常见于 Mac M1 Homebrew 安装)
别只盯着 ThinkPHP 日志里“数据库连接失败”这句废话,直接翻 runtime/log/ 下最新日志,找到带 PDOException 的那一行,复制完整 message 再判断。
host 和 port 看似写对了,为什么还是连不上
常见错位点不在配置语法,而在网络语义:
-
host别写localhost:它在多数系统下强制走 Unix socket;而你配的port是给 TCP 用的,两者不匹配。统一用127.0.0.1测试 -
port必须是整数:写成'3306'(字符串)会导致 ThinkPHP 5.1+ 传给 PDO 时类型不符,PDO 会静默 fallback 到默认端口 - Docker 环境中,
host不能写127.0.0.1或localhost,得换成容器名(如mysql)或宿主机网关(如host.docker.internal) - 云服务器上,MySQL 用户的
host字段必须是'%'或具体公网 IP,不能是'localhost'—— 否则远程请求直接被拒
env 文件覆盖配置没生效,怎么快速验证
.env 不是写了就能用,它有三个硬性前提:
- 文件必须放在项目根目录(和
think命令同级),不是config/或app/下 -
APP_DEBUG必须为true,否则环境变量加载逻辑会被跳过(这是最常被忽略的一点) - 键名必须全大写加下划线:
DB_HOST=127.0.0.1才有效,db_host或Db_Host都读不到
验证是否加载成功,控制器里临时加一行:dump(env('DB_HOST'));。输出 null 就说明上面三点至少有一条没满足。
MySQL 8.0+ 报 caching_sha2_password 错误怎么办
错误信息是:Authentication plugin 'caching_sha2_password' cannot be loaded。这不是 ThinkPHP 的锅,是 PHP 7.4 以下版本的 PDO 不支持 MySQL 8.0 默认认证方式。
- 别降级 MySQL,也别强行换驱动 —— 直接改用户认证方式更稳
- 登录 MySQL 执行:
ALTER USER 'your_user'@'%' IDENTIFIED WITH mysql_native_password BY 'your_password'; - 执行完记得
FLUSH PRIVILEGES; - 如果用户是
'your_user'@'localhost',就把'%'换成'localhost'
这个操作只影响指定用户,不影响其他用户或全局安全策略。改完立刻重试,不用重启 MySQL。
真正难排查的从来不是“连不上”,而是“看起来连上了,但第一次查询就卡住或超时”——这时候大概率是 DNS 解析慢、MySQL 的 wait_timeout 太短,或者事务闭包里漏掉了 commit/rollback,导致连接一直被占着不放。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











