循環(huán)從mysql連接池中獲取連接,不需要重復(fù)創(chuàng)建新的連接。
參考配置修改:可以參考下面的文章
防止訪問量過大,把連接數(shù)占滿了
?php
/**
* @author xuleyan
* @title mysql類
*/
class DbHelper{
//連接池
private $_pools = [];
//連接池大小
const POOLSIZE = 5;
const USERNAME = "root";
const PASSWORD = "root";
const HOST = "127.0.0.1";
const DB = "test";
public function __construct()
{
$db = self::DB;
$username = self::USERNAME;
$password = self::PASSWORD;
$host = self::HOST;
//持久化連接
$presistent = array(PDO::ATTR_PERSISTENT => true);
for ($i=0; $i self::POOLSIZE; $i++) {
$connection = new PDO("mysql:dbname=$db;host=$host", $username, $password);
// sleep(3);
array_push($this->_pools, $connection);
}
}
//從數(shù)據(jù)庫連接池中獲取一個數(shù)據(jù)庫鏈接資源
public function getConnection()
{
echo 'get' . count($this->_pools) . "br>";
if (count($this->_pools) > 0) {
$one = array_pop($this->_pools);
echo 'getAfter' . count($this->_pools) . "br>";
return $one;
} else {
throw new ErrorException ( "mark>數(shù)據(jù)庫連接池中已無鏈接資源,請稍后重試!/mark>" );
}
}
//將用完的數(shù)據(jù)庫鏈接資源放回到數(shù)據(jù)庫連接池
public function release($conn)
{
echo 'release' . count($this->_pools) . "br>";
if (count($this->_pools) >= self::POOLSIZE) {
throw new ErrorException ( "mark>數(shù)據(jù)庫連接池已滿!/mark>" );
} else {
array_push($this->_pools, $conn);
// $conn = null;
echo 'releaseAfter' . count($this->_pools) . "br>";
}
}
public function query($sql)
{
try {
$conn = $this->getConnection();
$res = $conn->query($sql);
$this->release($conn);
return $res;
} catch (ErrorException $e) {
print 'error:' . $e->getMessage();
die;
}
}
public function queryAll($sql)
{
try {
$conn = $this->getConnection();
$sth = $conn->prepare($sql);
$sth->execute();
$result = $sth->fetchAll();
return $result;
} catch (PDOException $e) {
print 'error:' . $e->getMessage();
die;
}
}
}
在另外的文件這樣調(diào)用
?php
require_once 'db.php';
$sql = 'select * from user';
$dbhelper = new DbHelper;
for ($i=0; $i 10; $i++) {
$res = $dbhelper->query($sql);
// var_dump($res) . PHP_EOL;
}
ThinkPHP連接MySQL的連接池使用方法
因為一個小bug,導(dǎo)致項目在某個晚上向mysql發(fā)送了大量的連接請求,同時mysql服務(wù)器的dns出現(xiàn)問題,導(dǎo)致反解超時。最后活活的把mysql服務(wù)器拖掛了。
最后bug修復(fù)了,并研究了一下增加 mysql連接池的辦法。
這兩天搜了一下,發(fā)現(xiàn)ThinkPHP文檔里沒有連接池的相關(guān)文檔。所以自己研究了下代碼。
首先: PHP常用的mysql擴(kuò)展庫有三種 : mysql, mysqli, pdo_mysql.
* mysqli 是不支持連接池的。
* pdo_mysql 支持,但是,thinkPHP的pdo擴(kuò)展不支持mysql,僅支持:'MSSQL','ORACLE','Ibase','OCI' . ( 見 Pdo.class.php 的第59行)
* mysql 支持,通過方法:mysql_pconnect . (具體參數(shù)可以看php官方文檔)
1 使ThinkPHP啟用 長連接的方式是:
class BaseMysql extends Model {
protected $connection = array(
'db_type' => 'mysql',
'db_user' => '***',
'db_pwd' => '*******',
'db_host' => '*******',
'db_port' => '3306',
'db_name' => 'custom',
'db_params' => array('persist' => true),
);
}
如果你認(rèn)為,配置這個就萬事大吉了,那就大錯特錯了。
2 mysql -> my.cnf修改配置:
[mysqld]
interactive_timeout =60 // 交互連接(mysql-client)的過期時間。
wait_timeout =30 // 長連接的過期時間時間。 這個一定要改啊!默認(rèn)是8個小時。 如果請求量大點,很快連接數(shù)就占滿了。
max_connections = 100 //最大連接數(shù),可以認(rèn)為是連接池的大小
3 php.ini 修改:
[MySql]
mysql.allow_persistent = On
mysql.max_persistent = 99 // 要小于mysql配置的最大連接數(shù)
mysql.max_links = 99
4 webserver如果是apache ,需要啟用keep-alive。 否則,一旦請求退出,長連接將無法再重用。
webserver 是nginx的情況:
pm = dynamic // 默認(rèn)啟動一些子進(jìn)程,用于處理http請求。
pm.max_children // 最大的子進(jìn)程數(shù)。 這個配置要小于 mysql 的max_connections。
5 如果發(fā)現(xiàn)還是不能用,請檢查操作系統(tǒng)的keepalive 是否啟用。
綜述:
需要 keep-alive 和 數(shù)據(jù)庫長連接同時啟用,否則長連接回白白的占用mysql的連接數(shù)資源,而無法重用。
對于 nginx + php-fpm 的情況,其實是保持了 php-fpm 子進(jìn)程與mysql的長連接。 前端的http請求被分配給哪個 php-fpm子進(jìn)程,該子進(jìn)程就重用自己與mysql 的長連接。
上述是一整天的研究結(jié)果,不完備的地方,請大家指出,在此先行謝過!
您可能感興趣的文章:- workerman寫mysql連接池的實例代碼
- 詳解Spring Boot Mysql 版本驅(qū)動連接池方案選擇
- Python 使用 PyMysql、DBUtils 創(chuàng)建連接池提升性能
- Node.js使用MySQL連接池的方法實例
- nodeJs實現(xiàn)基于連接池連接mysql的方法示例
- Node.js實現(xiàn)mysql連接池使用事務(wù)自動回收連接的方法示例
- Python MySQL數(shù)據(jù)庫連接池組件pymysqlpool詳解
- Java使用MySQL實現(xiàn)連接池代碼實例