connection timed out 错误在 thinkphp 6 中主因是连接建立超时,需在 dsn 中显式配置 connect_timeout=3 并使用 ip 地址绕过 dns;pdo::attr_timeout 仅控制查询执行超时,与建连无关;tp6.1+ 启用连接池后 get_timeout 才生效,单位毫秒;探测连接应监听 before_execute 事件并调用 getattribute。

Connection timed out 错误在 ThinkPHP 6 中大概率不是 PDO 连不上 MySQL,而是框架在等一个可用连接时卡住了。直接调大 MySQL 的 wait_timeout 或改 max_execution_time 是治标不治本,得从连接建立、复用、获取三个环节分别控制。
DSN 加 connect_timeout 控制 TCP 建连超时
这是最常被忽略的第一道防线。TP6 默认 DSN 不带连接层超时,一旦 DNS 慢或目标 IP 不可达,会卡满系统默认的 75 秒(Linux)或 30 秒(Windows)。
- 把配置里的
host改成 IP 地址,绕过 DNS 解析(如'hostname' => '192.168.1.100') - 在 DSN 中显式加
;connect_timeout=3,例如:mysql:host=192.168.1.100;port=3306;dbname=test;connect_timeout=3 - 注意:PHP 8.1+ 且 TP6.1+ 才真正透传该参数;若用 mysqlnd 驱动(PHP 默认),该参数可能被忽略——此时必须降级用
mysqli测试验证,或升级到 TP6.1+
params 中设 PDO::ATTR_TIMEOUT 仅控制查询执行,不控建连
很多人配了 'params' => [\PDO::ATTR_TIMEOUT => 2] 却发现连不上时还是卡很久,因为这个值只影响 query() 或 execute() 执行 SQL 的等待时间(比如锁表),和「连数据库」这件事完全无关。
- 它生效的前提是连接已建立成功,只是 SQL 执行卡住
- 若你遇到的是首次请求就卡 30 秒,别在这儿调,去查 DSN 和网络
- TP6.0 及更早版本甚至不读取这个配置,需确认是否被
think-ormv3.0+ 正确加载
连接池开启后,get_timeout 才管“等连接”超时
TP6.0 不支持连接池,pool 配置完全无效;只有 TP6.1+ + think-orm ^3.0 才真正启用连接池逻辑,此时 get_timeout 才起作用。
- 配置位置必须在具体数据库项下,例如:
'mysql' => [/* ... */, 'pool' => ['get_timeout' => 1000]] -
get_timeout单位是毫秒,设为1000表示最多等 1 秒,超时抛think\exception\PDOException - 若没触发池满场景(比如
max_active设得很大),这个超时根本不会触发;别指望它解决建连慢问题 - 异常容易被
Db::table()->select()内部静默重试掩盖,建议用try/catch显式捕获
手动探测连接存活要避开 SELECT 1 和构造函数
TP6 默认不自动重连,break_reconnect => true 仅用于主从切换失败兜底,不能解决 MySQL server has gone away。
- 可靠探测时机是
query()或execute()前,推荐监听think\db\Connection::before_execute事件 - 用
$pdo->getAttribute(PDO::ATTR_SERVER_INFO),比SELECT 1少一次 round-trip,也不进慢日志 - 不要在模型
initialize()或连接对象__clone()里做探测——连接未激活时调用会报错,且浪费资源 - 探测失败后必须先
$connection->close()再$connection->initConnect(true),否则旧 PDO 实例残留导致后续查询仍失败
复杂点在于:建连超时、查询超时、池获取超时、连接失效重连,四者触发条件、配置位置、生效版本全都不一样。线上出问题时,先看错误信息里带不带 Connection timed out(建连层)、MySQL server has gone away(连接断开)、还是 WaitTimeoutException(池排队),再对应查哪一层。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











