1. 程式人生 > 程式設計 >php封裝pdo例項以及pdo長連線的優缺點總結

php封裝pdo例項以及pdo長連線的優缺點總結

一、前言

最近需要寫來實現崩潰日誌的入庫,不出所料又是脫離於框架的,那麼行吧,咱們只能自己封裝相關操作了。博主這裡選擇了封裝pdo操作資料庫相關。

二、為什麼選擇pdo

眾所周知的,在早期的時候是帶有擴充套件的,但是後來由於過於古老缺失了mysql的新特性,因此主鍵沒落。

從php5開始,更建議大家使用mysqli擴充套件,這個是mysql擴充套件的增強版,是一個面向物件的MySQL介面,更容易使用。缺點是隻能操作mysql,不夠強大。

還有wajaXyngl就是pdo擴充套件了,這個是最豐富的的一個擴充套件,支援多種資料庫,重要的是,在安全上是比其他兩種擴充套件都要強的,通過使用prepared預處理更是有效的防止sql注入。因此,博主這裡選擇了封裝pdo相關的操作。

三、pdo的長連線

1、什麼是pdo的長連線

長連線顧名思義就是一直保持連線,相對於平時的短連線,每次請求都會重新建立連結來說,長連線可以有效的減少建立的過程,可以更好的節省效能。

在操作上是在連線資料庫的時候,多加一個引數:

$pdo = new PDO($dsn,$username,$passwd,[PDO::ATTR_PERSISTENT => true]);

後面的PDO::ATTR_PERSISTENT => true 就是開啟長連線的方法。

2、長連線對nginx無效嗎

博主在搜尋長連線相關知識的時候,看到一篇文章,結論是長連線僅適用於apache,不適用於nginx,這是真的嗎?

參考文章:https://www.jb51.net/article/133709.htm

大致結論是:長連線更多的是針對於apache的,因為apache維護一www.cppcns.com個程序池,開啟了apache mpm功能之後,apache會預設維持一個程序池,mysql長連線之後的連線,並沒有作為socet連線關閉,而是作為一個不釋放的東西,放進了程序池/執行緒池裡面去。

而對於nginx來說,長連線是無效的,指令碼執行結束則釋放資源?

3、php-fpm下的長連線測試

這裡前輩已經測試過了,咱們給出前輩的地址,大家有興趣的可以看看

結論:
事實證明php-fpm是可以實現長連線的,只是如果該程序空閒的話,會造成資源浪費。

php-fpm的配置檔案可以考慮設定pm.max_requests = 1000,代表每一個子程序的最大請求服務數量,如果超過了這個值,該子程序會被自動重啟。

比如max_requests這個引數,如果設定很大的話,那這個子程序要執行很多次才會重啟,假如這個請求發生了錯誤或者記憶體洩漏,那麼這個值設定很大是不合適的。但如果請求沒有問題,這個值設定小的話就會頻繁的重啟,這樣也會碰到不少502的問題,所以要仁者見仁,智者見智的設定了,這裡初始化設定1000,如果測試沒有記憶體洩漏等問題,可以再大一些。

4、長連線對事務的影響

參考博文地址:https://www.zhihu.com/question/62603122

總結: 如果業務併發比較大且帶有事務,不建議使用長連線的方式。

5、總結

博主在不斷的搜尋中,發現長連線要發揮出最佳效能始終是避不開連線池這點的,而php恰恰又不能很好的實現連線池,這點確實是有點小遺憾。

整體來說在php中是暫時無法配置和mysql的完美連線池的,在業務比較複雜的地方,還是謹慎試用長連線,每個連線都是1個執行緒,會造成大量的資源浪費。

如果是某些業務需要持續的資料庫操作,比如提交日誌介面等,那麼是可以考慮開啟長連線的,記得設定max_requests來定量關閉php-fpm連線,fpm關閉之後也會自動釋放mysql的連線。

還有pm.max_spare_servers設定伺服器空閒時最大php-fpm程序數量。

例如: pm.max_spare_servers = 25 如果空閒時,會檢查程序數,多於25個了,就會關閉幾個,達到25個的狀態。

擅長swoole的同學,可以參考這篇文章:
基於swoole擴充套件實現真正的PHP資料庫連線池

四、pdo部分demo的封裝

首先這部分博主是參考了一個網友的封裝,地址如下:

https://github.com/nadirvishun/php-pdo-class

這個網友基本的增刪改查都封裝好了,而且都有引數預處理,安全性還是可以的。不過既然作為一個基準的類,還是缺少一些東西。

1、斷線重連機制

例如重連函式:

/**
 * @params:重連函式,上限3次
 * @date:2020/3/18
 * @time:17:03
 */
public function customConnect()
{
    try {
        $this->pdo = new PDO($this->config['dsn'],$this->config['username'],$this->config['password'],$this->config['params']);
        $this->pdo->setAttwajaXynglribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION); //需要將錯誤處理模式變成異常模式
        return true;
    } catch (Exception $e) {
        if (stripos($e->getMessage(),'MySQL server has gone away') !== false || stripos($e->getMessage(),' bytes failed with errno=10053') !==false) {
            $this->close();
            $this->tryNums++;
            if ($this->tryNums > 3) {
                return false;
            }
            self::customConnect();
        } else {
            $this->throw_exception($e->getMessage());
            return false;
        }
    }
}

2、轉化php warnings為try…catch可捕獲的錯誤

這步原因是長連線會頻繁的造成mysql gone away錯誤,而這個錯誤是php 的warnings級別錯誤,try..catch根本就捕獲不到,所以博主這裡自定義錯誤處理函式來處理。

這部分是轉化php的warnings錯誤為try..catch可以捕獲的error錯誤,關於php的報錯機制以及錯誤處理這塊,咱們下篇再討論。

//自定義warnings處理函式set_error_handler('customException');//拿到warnngs錯誤之後,轉化為error錯誤丟擲,這樣就可以被try..catch捕獲function customException( $error_no,$error_msg,$error_file,$error_line){
    throw new \Exception($error_msg,null);
    //throw new \Exception($error_msg);}

3、析構方法回收資源

/**
 * destruct 關閉資料庫連線
 */
public function destruct()
{
    $this->pdo = null;
}

4、query的時候ping一下

public function query($sql = null,$param = null)
  {
      //檢測連線是否活躍
      $this->pdo_ping();
      //判斷之前是否有結果集
      if (!empty($this->PDOStatement)) {
          $this->free();
      }
      xxxxxxxxxx        }

5、下載地址

這四步完善之後,這個pdo的類還是可以用的,大家需要的話可以去百度雲上下載。

連結: https://pan.baidu.com/s/1Siz_bKlhEIVNV99Y0zTzqw 提取碼: ebqx

到此這篇關於php封裝pdo例項以及pdo長連線的優缺點總結的文章就介紹到這了,更多相關php封裝pdo例項及pdo長連線優缺點分析內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!