PHP訪問MySQL查詢超時處理的方法
<?php
//創(chuàng)建對象
$mysqli = mysqli_init();
//設(shè)置超時選項
$mysqli->options(MYSQLI_OPT_CONNECT_TIMEOUT, 5);
//連接
$mysqli->real_connect('localhost', 'my_user', 'my_password', 'world');
//如果超時或者其他連接失敗打印錯誤信息
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
//成功輸出連接信息
printf ("Connection: %s\n.", $mysqli->host_info);
$mysqli->close();
?>
這個是連接超時,但是有些時候我們需要查詢讀寫超時,比如說我們一個數(shù)據(jù)庫壓力很大,或者連接很多,那么數(shù)據(jù)庫查詢就很緩慢,但是我希望某些不重要的數(shù)據(jù),比如說文章點擊數(shù)這種如果查詢超時了就不顯示,至少能夠保證主體頁面正確顯示,但是查遍PHP手冊沒有發(fā)現(xiàn)這個操作選項或者函數(shù)。
手冊里只有這么四個選項
跟蹤 mysqli 的擴展源代碼發(fā)現(xiàn)它底層調(diào)用的是 libmysqlclient 的 mysql_options:
php-5.2.8/ext/mysqli/mysqli_api.c
并且在mysqli的PHP擴展中就只導(dǎo)出了幾個變量:
php-5.2.8/ext/mysqli/mysqli.c
大概看了一下 libmysqlclient 的代碼,發(fā)現(xiàn)其實它自帶是有讀寫超時設(shè)置的:
mysql-5.1.30/sql-common/client.c
因為它自己定義了很多操作選項,只是php擴展里沒有:
mysql-5.1.30/include/mysql.h
看看mysql中的讀寫超時是如何實現(xiàn)的:
mysql-5.1.30/sql-common/client.c
讀寫超時真正操作的地方,超時處理這里重試了兩次,還是寫死了:
mysql-5.1.30/sql/net_serv.cc
現(xiàn)在基本得出了結(jié)論:
按照上面查看代碼來看,目前PHP針對MySQL查詢超時以下限制: 1. 超時設(shè)置單位為秒,最少配置1秒 2. 但mysql底層的read會重試兩次,所以實際會是 3 秒 重試兩次 + 自身一次 = 3倍超時時間。 那么就是說最少超時時間是3秒,不會低于這個值,對于大部分應(yīng)用來說可以接受,但是對于小部分應(yīng)用需要優(yōu)化。 查看上面代碼的執(zhí)行結(jié)果,驗證了上面的觀點,第一個查詢成功了,第二個查詢連接被斷開了:
如果需要修改這個秒級別的超時,比如改成毫秒級別的超時,只能兩個地方修改: 1. 修改客戶端,比如 mysqli 的 query 代碼,加入定時器,超時則返回 2. 修改 Mysql 中的vio代碼,因為mysql的網(wǎng)絡(luò)處理底層都是經(jīng)過vio的操作
MySQL相關(guān)的vio代碼:
poll 超時:
setsockopt 超時:
基本上到這里就基本能夠解決PHP在針對MySQL讀寫查詢操作超時的處理了,希望對你有幫助。
現(xiàn)在我們來看看如果我們自己要設(shè)置超時,我們自己壓入 MYSQL_OPT_READ_TIMEOUT 也是可以達到讀寫超時效果的,寫一段代碼來測試一下:
<?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);
}
//設(shè)置超時
$mysqli = mysqli_init();
$mysqli->options(MYSQL_OPT_READ_TIMEOUT, 3);
$mysqli->options(MYSQL_OPT_WRITE_TIMEOUT, 1);
//連接數(shù)據(jù)庫
$mysqli->real_connect("localhost", "root", "root", "test");
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
//執(zhí)行查詢 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";
}
//執(zhí)行查詢 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";
?>
heiyeluren的blog
相關(guān)文章
mysql導(dǎo)入sql文件命令和mysql遠程登陸使用詳解
這篇文章主要介紹了mysql導(dǎo)入sql文件命令和mysql遠程登陸使用詳解,需要的朋友可以參考下2014-04-04centos7環(huán)境下二進制安裝包安裝 mysql5.6的方法詳解
這篇文章主要介紹了centos7環(huán)境下二進制安裝包安裝 mysql5.6的方法,詳細分析了centos7環(huán)境下使用二進制安裝包安裝 mysql5.6的具體步驟、相關(guān)命令、配置方法及操作注意事項,需要的朋友可以參考下2020-02-02mysql中secure_file_priv=不生效問題及解決
這篇文章主要介紹了mysql中secure_file_priv=不生效問題及解決方案,以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家,2024-01-01MySQL數(shù)據(jù)庫中null的知識點總結(jié)
在本篇文章里小編給大家整理的是關(guān)于MySQL數(shù)據(jù)庫null的知識點以及相關(guān)實例,需要的朋友們可以學(xué)習(xí)下。2019-10-10