php设置mysql查询读取数据的超时时间

作者:袖梨 2022-06-24


现象:php能通过代理正常连接到mysql。但是,执行query后,一直等待,没有任何数据返回。
结果导致php-fpm进程全部阻塞在读取数据的地方。不能处理其他正常请求。解决方法:
可以通过设置mysql查杀的超时时间来解决这个问题。
第一种设置mysql查询超时时间的方法是使用mysqlnd。

php启用mysqlnd扩展后,只要在php.ini文件中设置 mysqlnd.net_read_timeout 即可。

参数值的单位为秒。如:

mysqlnd.net_read_timeout = 3 表示每次mysql查询超时时间为3秒。如果超时,则会报错。

如下面的代码:
query("set names utf8");
$sql = "select sleep(5)";
$sth = $dbh->query($sql);
$row = $sth->fetch();
echo "over";
?>

Baseline; word-break: break-all; color: rgb(68, 68, 68); font-family: " microsoft="" yahei",="" "helvetica="" neue",="" helvetica,="" arial,="" sans-serif;="" line-height:="" 21px;="" background-color:="" rgb(255,="" 255,="" 255);"=""> 则会报错误:
PHP Warning: PDO::query(): MySQL server has gone away
PHP Warning: PDO::query(): Error reading result set's header
PHP Fatal error: Call to a member function fetch() on a non-object

由于出现了PHP Fatal error错误,导致fetch()之后的代码将无法执行。
​因此代码需要对query的返回值做下判断,修改后的代码如下:

query("set names utf8");
$sql = "select sleep(5)";
$sth = $dbh->query($sql);
if(is_object($sth)){
    $row = $sth->fetch();
}
echo "over";
?>
注意:设置项 mysqlnd.net_read_timeout 的级别是PHP_INI_SYSTEM。所以在php代码中不能修改mysql查询的超时时间。

另一种方式是使用mysqli。
如果php没有启用mysqlnd,那么可以使用mysqli进行限制read的超时时间。
示例代码如下:

options(MYSQL_OPT_READ_TIMEOUT, 3);
$mysqli->options(MYSQL_OPT_WRITE_TIMEOUT, 1);
//连接数据库
$mysqli->real_connect("localhost", "root", "root", "test");
if (mysqli_connect_errno()) {
   printf("Connect failed: %s/n", mysqli_connect_error());
   exit();
}
//执行查询 sleep 1秒不超时
printf("Host information: %s/n", $mysqli->host_info);
if (!($res=$mysqli->query('select sleep(1)'))) {
    echo "query1 error: ". $mysqli->error ."/n";
} else {
    echo "Query1: query success/n";
}
//执行查询 sleep 9秒会超时
if (!($res=$mysqli->query('select sleep(9)'))) {
    echo "query2 error: ". $mysqli->error ."/n";
} else {
    echo "Query2: query success/n";
}
$mysqli->close();
echo "close mysql connection/n";
?>
注意:

1. 超时设置单位为秒,最少配置1秒
2. 但mysql底层的read会重试两次,所以实际会是 3 秒
重试两次 + 自身一次 = 3倍超时时间。
那么就是说最少超时时间是3秒,不会低于这个值,对于大部分应用来说可以接受,但是对于小部分应用需要优化。


当然有mysql配置权限可以参考下面方法修改超时时间

mysql> show variables like ‘%timeout’;
mysql> set wait_timeout = 28800000;
mysql> set interactive_timeout = 28800000;

 修改操作如下:打开/etc/my.cnf,在属性组mysqld下面添加参数如下:

[mysqld]
interactive_timeout=28800000
wait_timeout=28800000
windows下在my.ini文中增加:
interactive_timeout=28800000
wait_timeout=28800000

或者使用命令

查看mysql server超时时间:

   msyql> show global variables like '%timeout%';
 
设置mysql server超时时间(以秒为单位):
 
  msyql> set global wait_timeout=10;

  msyql> set global interactive_timeout=10;


现对wait_timeout的最大值分别是24天/365天(windows/linux)。以windows为 例,假设我们要将其设为21天,我们只要修改mysql5的配置文件“my.ini”(mysql5 installation dir),增加一行:wait_timeout=18144006
需要重新启动mysql5。

相关文章

精彩推荐