一次php脚本执行过程当中屡次实例化PDO的情景分析

情景分析

脚本代码:php

<?php

try {
    $dbh1 = new PDO('mysql:host=localhost;dbname=test', 'root', 'root');
} catch (PDOException $e) {
    exit('链接数据库失败1');
} finally {
    echo "链接成功1\n";
}

try {
    $dbh2 = new PDO('mysql:host=localhost;dbname=test', 'root', 'root');
} catch (PDOException $e) {
    exit('链接数据库失败2');
} finally {
    echo "链接成功2\n";
}

try {
    $dbh3 = new PDO('mysql:host=localhost;dbname=test', 'root', 'root');
} catch (PDOException $e) {
    exit('链接数据库失败3');
} finally {
    echo "链接成功3\n";
}

echo "保持链接中...\n";
sleep(10);
echo "执行结束\n";

CLI执行:mysql

root@78ad0df34cef:/home/www/test# php index.php
链接成功1
链接成功2
链接成功3
保持链接中...
执行结束

在脚本sleep过程当中,咱们查看mysql的链接信息:web

mysql> show processlist;
+----+------+-----------+------+---------+------+----------+------------------+
| Id | User | Host      | db   | Command | Time | State    | Info             |
+----+------+-----------+------+---------+------+----------+------------------+
|  3 | root | localhost | NULL | Query   |    0 | starting | show processlist |
| 24 | root | localhost | test | Sleep   |    6 |          | NULL             |
| 25 | root | localhost | test | Sleep   |    6 |          | NULL             |
| 26 | root | localhost | test | Sleep   |    6 |          | NULL             |
+----+------+-----------+------+---------+------+----------+------------------+
4 rows in set (0.00 sec)

能够看到一个脚本的执行产生了三个数据库链接,可是若是将后面的实例化的pdo实例赋值给以前实例化的pdo实例,则新的链接会替换掉前一个链接,而不会产生新的链接。因此咱们在编程过程当中,应该避免屡次实例化pdo,而产生没必要要的数据库性能消耗。sql

解决方案

  1. 封装一个单例模式的类,该类实例化的过程就是建立pdo链接的过程。咱们要创建数据库链接时,不是手动实例化pdo,而是去获取这个类的实例。
  2. 实例化pdo类时,设定 持久链接 参数:
<?php
$dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass, array(
    PDO::ATTR_PERSISTENT => true
));
?>

PHP官方文档的引用:数据库

不少 web 应用程序经过使用到数据库服务的持久链接得到好处。 持久链接在脚本结束后不会被关闭,且被缓存,当另外一个使用相同凭证的脚本链接请求时被重用。持久链接缓存能够避免每次脚本须要与数据库回话时创建一个新链接的开销,从而让web 应用程序更快。

官方所说的脚本结束,在fpm模式下就是指一次客户端请求的结束另外一个使用相同凭证的脚本也就能够对应成另外一个使用相同数据库链接凭证的客户端请求。首先咱们要知道,这两次客户端的请求是根据fpm-workers的空闲状况,被分配给某个worker去执行的,因此两次请求被分配到同一个worker的可能性很低。接着,咱们阐明下面的情景。编程

开启持久链接以后,数据库链接是被缓存于fpm进程之中的。若是某个fpm-worker进程中已经缓存了持久链接,此时可能出现以下两种状况:缓存

  • 当脚本中再次执行带 ATTR_PERSISTENT 参数的pdo链接时,会复用以前的链接,而不会产生新的链接。
  • 当脚本中再次执行不带 ATTR_PERSISTENT 参数的pdo链接时,还会再次产生一个新的数据库链接。
相关文章
相关标签/搜索