脚本代码: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
<?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进程中已经缓存了持久链接,此时可能出现以下两种状况:缓存