PHP+MariaDBでDB連携(コネクションプール)

次はDBとのコネクションプール(持続的DB接続)について調べる。
毎回コネクションの接続・切断を繰り返していると性能がでないため、使い終わったコネクションを切断せずにプールに入れておき、その後使用したい別の人が現れた時に、プールからコネクションを出してきて初期化だけして再利用するもの。

 

どのようなコードを書けば良いのか

・mysqli モジュールの場合 (マニュアルページ)

 DB接続する際に、ホスト名の前に「p:」をつけるだけで良い。

 

 p:を付けるだけで、下記のコーディングは、プールにあるアイドル状態のコネクションを再利用するという動きに変わってくれる。プールにアイドル状態のコネクションがない場合は、これまで通り、新規コネクションを接続する。
 $mysqli = new mysqli("p:localhost", "user001", "pass001", "db002");

 

 また、下記の切断時のコーデイングに変わりはないが、「p:」付きで接続した際はコネクションをプールに戻すという動きになるし、「p:」を付けずに接続した場合の下記のコードは、コネクションを解放するという動きになる。

 $mysqli->close();

 

本当にプーリングされているのか実験

まずは、ホスト名に「p:」を付けずに実験。

最初に、mysqlクライアントを起動しMariaDBのコネクション数を確認。

MariaDB [db002]> show status like 'Threads_connected';

その結果、mysqlクライアント自身の数と思われる "1" になっていた。

 

次に、以下のPHPスクリプトにブラウザからアクセスする。

 <?php
$mysqli = new mysqli("localhost", "user001", "pass001", "db002");
$mysqli->set_charset("utf-8");
$result = $mysqli->query("SELECT name FROM tbl");
$loop=true;

while ($loop) {
 $row = $result->fetch_assoc();
 if ($row == Null) {
  break;
 } else {
  echo 'name=' . htmlentities($row['name']) . 'だよ-<br>';
 }
}
$result->free();
$mysqli->close();
?>

 

再度、コネクション数を確認した。

MariaDB [db002]> show status like 'Threads_connected';

結果は、変化なし。$mysqli->close();のコードにより、コネクションが切断されたためと思われる。

 

では次に、ホスト名の前に「p:」を付けて実験する。

MariaDB [db002]> show status like 'Threads_connected';

結果は、コネクション数が2になった。何度か繰り替えしブラウザをリロードしてみたが、常に2となった。新たに接続した2つ目のコネクションは、$mysqli->close();を実行した際に、コネクションを切断せずにプールに戻されたと思われる。その後は、プール内にアイドル状態のコネクションがあるうちは再利用されるため、新たなコネクションを確立することはない。

 

 

本当に性能は上がるのか実験

 

コネクションプーリングを使用すると本当に性能が上がるのか、実験する。SELECT文を5,000回実行する。実験に使用するPHPコードは以下。

<?php
$start = (new DateTime())->getTimestamp();
echo "start= $start<br>\n";

for ($i=0; $i<5000; $i++) {
 $mysqli = new mysqli("localhost", "user001", "pass001", "db002");
 $mysqli->set_charset("utf-8");
 $result = $mysqli->query("SELECT name FROM tbl");
 $row = $result->fetch_assoc();
 if ($row == Null) {
  break;
 } else {
  $tmp = 'name=' . htmlentities($row['name']) . 'だよ-<br>';
 }
 $result->free();
 $mysqli->close();
 unset($tmp, $row, $result, $mysqli);
}
$end = (new DateTime())->getTimestamp();
echo "end = $end<br>\n";

echo '終わり。経過時間[秒]=' . ($end - $start);
?>

 

・プールしない場合

26秒

・プールする場合

3秒

 

こんなにも差が出るんだね。

 

  

---------------------------------------
 ■ITとことんのトップページ
  ┗■PHPのトップページ
    ┗■本ページ