迴圈從mysql串連池中擷取串連,不需要重複建立新的串連。本文主要介紹了php代碼實現mysql串連池效果,需要的朋友可以參考下,希望能協助到大家。
參考配置修改:可以參考下面的文章
防止訪問量過大,把串連數佔滿了
<?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); } } //從資料庫連接池中擷取一個資料庫連結資源 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>資料庫連接池中已無連結資源,請稍後重試!</mark>" ); } } //將用完的資料庫連結資源放回到資料庫連接池 public function release($conn) { echo 'release' . count($this->_pools) . "<br>"; if (count($this->_pools) >= self::POOLSIZE) { throw new ErrorException ( "<mark>資料庫連接池已滿!</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; } }}
在另外的檔案這樣調用
<?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,導致項目在某個晚上向mysql發送了大量的串連請求,同時mysql伺服器的dns出現問題,導致反解逾時。最後活活的把mysql伺服器拖掛了。
最後bug修複了,並研究了一下增加 mysql串連池的辦法。
這兩天搜了一下,發現ThinkPHP文檔裡沒有串連池的相關文檔。所以自己研究了下代碼。
首先: PHP常用的mysql擴充庫有三種 : mysql, mysqli, pdo_mysql.
* mysqli 是不支援串連池的。
* pdo_mysql 支援,但是,thinkPHP的pdo擴充不支援mysql,僅支援:'MSSQL','ORACLE','Ibase','OCI' . ( 見 Pdo.class.php 的第59行)
* mysql 支援,通過方法:mysql_pconnect . (具體參數可以看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), );}
如果你認為,配置這個就萬事大吉了,那就大錯特錯了。
2 mysql -> my.cnf修改配置:
[mysqld]
interactive_timeout =60 // 互動串連(mysql-client)的到期時間。
wait_timeout =30 // 長串連的到期時間時間。 這個一定要改啊!預設是8個小時。 如果請求量大點,很快串連數就佔滿了。
max_connections = 100 //最大串連數,可以認為是串連池的大小
3 php.ini 修改:
[MySql]
mysql.allow_persistent = On
mysql.max_persistent = 99 // 要小於mysql配置的最大串連數
mysql.max_links = 99
4 webserver如果是apache ,需要啟用keep-alive。 否則,一旦請求退出,長串連將無法再重用。
webserver 是nginx的情況:
pm = dynamic // 預設啟動一些子進程,用於處理http請求。
pm.max_children // 最大的子進程數。 這個配置要小於 mysql 的max_connections。
5 如果發現還是不能用,請檢查作業系統的keepalive 是否啟用。
綜述:
需要 keep-alive 和 資料庫長串連同時啟用,否則長串連回白白的佔用mysql的串連數資源,而無法重用。
對於 nginx + php-fpm 的情況,其實是保持了 php-fpm 子進程與mysql的長串連。 前端的http請求被分配給哪個 php-fpm子進程,該子進程就重用自己與mysql 的長串連。