php設定mysql查詢讀取資料的逾時時間

來源:互聯網
上載者:User


現象:php能通過代理正常串連到mysql。但是,執行query後,一直等待,沒有任何資料返回。
結果導致php-fpm進程全部阻塞在讀取資料的地方。不能處理其他正常請求。解決方案:
可以通過設定mysql查殺的逾時時間來解決這個問題。
第一種設定mysql查詢逾時時間的方法是使用mysqlnd。

php啟用mysqlnd擴充後,只要在php.ini檔案中設定 mysqlnd.net_read_timeout 即可。

參數值的單位為秒。如:

mysqlnd.net_read_timeout = 3 表示每次mysql查詢逾時時間為3秒。如果逾時,則會報錯。

如下面的代碼:
<!--?php
$dsn = 'mysql:dbname=demo;host=127.0.0.1;port=3306';
$user = 'demo';
$password = 'demo';
$dbh = new PDO($dsn, $user, $password);
$dbh----->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的傳回值做下判斷,修改後的代碼如下:

<!--?php
$dsn = 'mysql:dbname=demo;host=127.0.0.1;port=3306';
$user = 'demo';
$password = 'demo';
$dbh = new PDO($dsn, $user, $password);
$dbh----->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的逾時時間。
範例程式碼如下:

<!--?php
//自己定義讀寫逾時常量
if (!defined('MYSQL_OPT_READ_TIMEOUT')) {
        define('MYSQL_OPT_READ_TIMEOUT',  11);
}
if (!defined('MYSQL_OPT_WRITE_TIMEOUT')) {
        define('MYSQL_OPT_WRITE_TIMEOUT', 12);
}
//設定逾時
$mysqli = mysqli_init();
$mysqli----->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。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.