TP6.0数据库连接失败首先发生在PDO实例化阶段,常见SQLSTATE[HY000] [1045]错误源于账号密码错误或MySQL用户未授权当前IP访问,需检查.env与配置文件密码一致性及用户host权限。

TP6.0 连不上数据库,先看 PDO 实例化阶段报什么错
连接失败根本不在 Db::table()->select() 阶段,而是在 new PDO() 构造函数执行时就崩了——这时候你设的 PDO::ATTR_ERRMODE 还没生效,捕获不到任何提示。
必须用 try/catch 包住整个连接初始化过程,否则只会静默失败或抛出 PHP Fatal Error。常见错误码含义要盯住:
-
SQLSTATE[HY000] [2003]:网络不通,host写成localhost却期望走 TCP;换成127.0.0.1或真实 IP 立刻验证 -
SQLSTATE[HY000] [1045]:账号密码错,或 MySQL 用户没授权从当前 IP 登录(比如只给了'user'@'localhost') -
SQLSTATE[HY000] [2002]:Unix socket 路径不对,或host=localhost强制走 socket 但文件不存在
别信日志里“连接超时”四个字——先 var_dump($e->getCode(), $e->getMessage()),再动手改配置。
TP6.0 的 'pool' 配置完全无效,别白调
TP6.0 不支持连接池,所有 'pool' => ['get_timeout' => 1000] 这类配置都会被忽略。你看到的“连接超时”大概率不是等不到池中连接,而是建连本身卡住了。
真正起作用的只有两处:
- DSN 中加
connect_timeout=3(仅 PHP 8.1+ + TP6.1+ 才透传,TP6.0 下基本不生效) - MySQL 服务端的
wait_timeout和max_connections,但这只是兜底,不能解决建连慢
TP6.0 没有连接池逻辑,所谓“池满”“获取超时”都是幻觉。如果你在 TP6.0 里配了 pool 还报错,说明问题根本不在池,而在 DNS、防火墙、MySQL 是否监听、PHP 是否加载 pdo_mysql 扩展这些基础环节。
TP6.0 不读 PDO::ATTR_TIMEOUT,别往 params 里塞
很多人在数据库配置里写 'params' => [\PDO::ATTR_TIMEOUT => 2],结果连不上时还是卡 30 秒——因为这个参数只控制 execute() 执行 SQL 的超时,对 new PDO() 建连毫无影响。
更关键的是:TP6.0 及更早版本压根不读这个配置项。它只在 TP6.1+ + think-orm v3.0+ 中才被正确加载。
想控建连时间,唯一靠谱方式是:
- 把
hostname改成 IP(绕过 DNS) - 确认 PHP 进程能
ping通该 IP + 端口(用telnet 192.168.1.100 3306测试) - 检查 MySQL 是否绑定了
bind-address = 0.0.0.0(而非仅127.0.0.1)
TP6.0 默认不校验连接存活,“MySQL server has gone away” 必现
TP6.0 没有 check_conn 选项,也不支持 break_reconnect 自动重连(那是 TP6.3+ 才加的)。一旦连接空闲超过 MySQL 的 wait_timeout(默认 28800 秒),下次复用就会直接报 SQLSTATE[HY000] [2006] MySQL server has gone away。
这不是 bug,是设计如此。解决方案只有两个硬招:
- 关掉持久连接:
'persistent' => false(TP6.0 默认就是 false,但有人手动开了) - 在每次查询前自己探测:
$pdo->getAttribute(\PDO::ATTR_SERVER_INFO),失败则重建连接——但 TP6.0 没提供钩子,得自己封装 Db 类
别指望 TP6.0 自动处理连接断开。它的连接管理模型就是“拿了就用,用完归还”,中间不插任何健康检查。复杂点在于:你得自己判断什么时候该重连,而不是等框架告诉你。


















