pdo连接超时必须用pdo::attr_timeout整型参数,设于params数组中,控制tcp握手前等待时间;错误使用'timeout'等字符串键名将被忽略,退至系统默认75秒。

PDO连接建立超时:必须用PDO::ATTR_TIMEOUT,不是timeout
PDO本身不认timeout、connect_timeout这类字符串键名,只认PDO::ATTR_TIMEOUT这个整型属性。它控制的是TCP握手完成前的最大等待时间,单位是秒。
常见错误写法:['timeout' => 3]或['connect_timeout' => 3]——这些配置完全被忽略,PDO会退回到系统默认(Linux常为75秒)。
- 必须写在
params数组里,例如:['params' => [PDO::ATTR_TIMEOUT => 3]] - 仅对
new PDO()或ThinkPHP中Db::connect([...])等显式创建连接生效;Db::table()->select()这类调用不走这里 - 设为
0等于无限等待,生产环境严禁使用 - 搭配
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION才能捕获到PDOException,否则超时失败静默吞掉
PDO读取/写入超时:MySQLi才稳定支持,PDO驱动差异大
PDO::MYSQL_ATTR_READ_TIMEOUT和PDO::MYSQL_ATTR_WRITE_TIMEOUT在phpEnv或旧版PHP(
验证方法:故意把MySQL服务停掉,看是不是真在3秒后抛异常,还是等满系统TCP超时才失败。
- 推荐改用
mysqli_init()+mysqli_options($link, MYSQLI_OPT_CONNECT_TIMEOUT, 3)组合,兼容性更好 - 若坚持用PDO,DSN里加
connect_timeout=3(如mysql:host=127.0.0.1;dbname=test;connect_timeout=3)在部分环境更可靠 - 注意:host别写
localhost,Windows下会走socket,绕过TCP超时控制;换成127.0.0.1
SQL执行超时:PDO不自动发SET SESSION max_execution_time
PDO连接成功后,默认不会帮你设置MySQL会话级查询超时。哪怕你全局配了max_execution_time=1000,单条慢查询仍可能跑满服务器限制(默认300秒)。
必须在执行长SQL前手动触发:
- PHP中:
$pdo->exec("SET SESSION max_execution_time = 120000");(单位毫秒) - 这条语句要放在
$pdo->query($sql)之前,且每次连接都需要重设(持久连接除外) - MySQL 5.7.8+才支持该变量;低于此版本需靠应用层计时+中断,或改用
KILL QUERY - 注意:这仅限制单条语句执行时间,不影响连接建立或网络传输阶段
CLI环境下容易漏的default_socket_timeout
命令行运行PHP脚本时,default_socket_timeout(php.ini里)会作为底层socket默认超时兜底。如果PDO没设PDO::ATTR_TIMEOUT,它就起作用;设了也会被部分驱动当作读写超时参考值。
- 建议同步调低该值,比如设为
10(秒),避免CLI任务卡死 - 修改位置:php.ini中
default_socket_timeout = 10,改完需重启PHP-FPM或CLI进程 - ThinkPHP CLI命令中,还需确认数据库配置里
'break_reconnect' => true已开启,否则空闲断连后无法自动恢复
new PDO()就可能卡75秒。











