腳本代碼: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進程中已經緩存了持久鏈接,此時可能出現以下兩種狀況:緩存