PHP8项目数据库查询卡30秒才报错,说明读写超时未设:MySQLi需mysqli_init()+mysqli_options()设CONNECT/READ/WRITE超时;PDO推荐DSN加connect_timeout或options数组配ATTR_TIMEOUT、MYSQL_ATTR_READ_TIMEOUT等;全局php.ini中mysqli.default_socket_timeout和pdo_mysql.default_socket_timeout须同步设为略大于业务超时值。

PHP8项目中数据库查询卡住30秒才报错,或写入操作突然中断无响应,说明读写超时未被正确控制,必须在连接建立后立即设置对应参数,否则会沿用系统级75秒TCP超时。
MySQLi扩展读写超时配置
第一步:使用mysqli_init()初始化连接对象,不能直接调用mysqli_connect()——后者不接受超时参数,会导致MYSQLI_OPT_READ_TIMEOUT等设置失效。
第二步:在mysqli_real_connect()之前,依次调用mysqli_options()设置三项关键超时:
mysqli_options($mysqli, MYSQLI_OPT_CONNECT_TIMEOUT, 5);
mysqli_options($mysqli, MYSQLI_OPT_READ_TIMEOUT, 12);
mysqli_options($mysqli, MYSQLI_OPT_WRITE_TIMEOUT, 8);
立即学习“PHP免费学习笔记(深入)”;
第三步:执行mysqli_real_connect()完成连接。注意【READ和WRITE超时值必须小于脚本总执行时间(如set_time_limit(30)),否则会被上层截断】。
PDO扩展的可靠超时写法
方法一:DSN中显式声明connect_timeout(仅MySQL 5.6+且非mysqlnd驱动下稳定生效):
$dsn = "mysql:host=192.168.1.100;dbname=test;connect_timeout=5";
方法二:构造PDO实例时传入options数组(mysqlnd驱动下ATTR_TIMEOUT和MYSQL_ATTR_READ_TIMEOUT更可靠):
$pdo = new PDO($dsn, $user, $pass, [
PDO::ATTR_TIMEOUT => 5,
PDO::MYSQL_ATTR_CONNECT_TIMEOUT => 5,
PDO::MYSQL_ATTR_READ_TIMEOUT => 15,
PDO::MYSQL_ATTR_WRITE_TIMEOUT => 10
]);
注意:PDO::ATTR_TIMEOUT在PHP 8.1+中对mysqlnd驱动生效,旧版本请优先用方法一或改用MySQLi。
全局socket超时兜底设置
编辑php.ini,定位到[mysqli]和[pdo_mysql]节区:
mysqli.default_socket_timeout = 15
pdo_mysql.default_socket_timeout = 15
该值作为所有未显式设置超时的MySQLi/PDO连接的最终 fallback,必须比业务层读写超时略大,但不可超过Web服务器fastcgi_read_timeout值,否则会被Nginx/Apache主动切断。
CLI模式下强制中断长耗时查询
仅限命令行脚本,Web环境禁用:在查询前注册信号处理器,5秒未返回则触发SIGALRM终止:
pcntl_alarm(5);
pcntl_signal(SIGALRM, function() { die("Query timeout\n"); });
$stmt = $pdo->query("SELECT SLEEP(10)");
这一步必须配合pcntl_signal_dispatch()或declare(ticks=1),否则信号可能延迟响应。



















