zoukankan      html  css  js  c++  java
  • 一个php脚本执行中实例多次PDO,会建立多次数据库连接。

    脚本代码:

    <?php
    
    try {
    
        $dbh = new PDO('mysql:host=localhost;dbname=test', 'root', 'root');
    
    } catch (PDOException $e) {
    
        exit('连接数据库失败1');
    
    } finally {
    
        echo "连接成功1
    ";
    
    }
    
    try {
    
        $conn = new PDO('mysql:host=localhost;dbname=test', 'root', 'root');
    
    } catch (PDOException $e) {
    
        exit('连接数据库失败2');
    
    } finally {
    
        echo "连接成功2
    ";
    
    }
    
    try {
    
        $pdo = new PDO('mysql:host=localhost;dbname=test', 'root', 'root');
    
    } catch (PDOException $e) {
    
        exit('连接数据库失败3');
    
    } finally {
    
        echo "连接成功3
    ";
    
    }
    
    echo "保持连接中...
    ";
    sleep(10);
    echo "执行结束
    ";

    CLI执行:

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

    在脚本sleep过程中,查看mysql的连接信息:

    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,而产生不必要的数据库性能消耗。

    解决方案:

    1. 封装一个单例模式的类,该类实例化的过程就是创建pdo连接的过程。我们要建立数据库连接时,不是手动实例化pdo,而是去获取这个类的实例。

    2. 实例化pdo类时,设定 持久连接 参数:

      

    <?php
    $dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass, array(
        PDO::ATTR_PERSISTENT => true
    ));
    ?>

    官方文档的引用:

    很多 web 应用程序通过使用到数据库服务的持久连接获得好处。持久连接在脚本结束后不会被关闭,且被缓存,当另一个使用相同凭证的脚本连接请求时被重用。持久连接缓存可以避免每次脚本需要与数据库回话时建立一个新连接的开销,从而让 web 应用程序更快。
    1. 官方所说的脚本结束,在fpm模式下就是指一次客户端请求的结束另一个使用相同凭证的脚本也就可以对应成另一个使用相同数据库连接凭证的客户端请求。首先我们要知道,这两次客户端的请求是根据fpm-workers的空闲情况,被分配给某个worker去执行的,所以两次请求被分配到同一个worker的可能性很低。接着,我们阐明下面的情景。
    2. 2. 开启持久连接之后,数据库连接是被缓存于fpm进程之中的。如果某个fpm-worker进程中已经缓存了持久连接,此时可能出现如下两种情况:
      • 当脚本中再次执行带 ATTR_PERSISTENT 参数的pdo连接时,会复用之前的连接,而不会产生新的连接。
      • 当脚本中再次执行不带 ATTR_PERSISTENT 参数的pdo连接时,还会再次产生一个新的数据库连接。

  • 相关阅读:
    快照原理及场景
    CEP实时分析模型
    请求响应模式
    JMS消息服务模型
    EMF与GEF
    基于SOA的编程模型
    实时计算CEP
    数据库常见的场景
    自签证书服务加入证书验证
    post提交主订单数据(gateway)实现httpapi
  • 原文地址:https://www.cnblogs.com/xingyazhao/p/8569496.html
Copyright © 2011-2022 走看看