php封裝pdo實例以及pdo長連接的優(yōu)缺點總結
一、前言
最近需要寫腳本來實現(xiàn)崩潰日志的入庫,不出所料又是脫離于框架的,那么行吧,咱們只能自己封裝數(shù)據(jù)庫相關操作了。博主這里選擇了封裝pdo操作數(shù)據(jù)庫相關。
二、為什么選擇pdo
眾所周知的,php在早期的時候是帶有mysql擴展的,但是后來由于過于古老缺失了mysql的新特性,因此主鍵沒落。
從php5開始,更建議大家使用mysqli擴展,這個是mysql擴展的增強版,是一個面向對象的MySQL接口,更容易使用。缺點是只能操作mysql,不夠強大。
還有就是pdo擴展了,這個是最豐富的的一個擴展,支持多種數(shù)據(jù)庫,重要的是,在安全上是比其他兩種擴展都要強的,通過使用prepared預處理更是有效的防止sql注入。因此,博主這里選擇了封裝pdo相關的操作。
三、pdo的長連接
1、什么是pdo的長連接
長連接顧名思義就是一直保持連接,相對于平時的短連接,每次請求都會重新創(chuàng)建鏈接來說,長連接可以有效的減少創(chuàng)建的過程,可以更好的節(jié)省性能。
在操作上是在連接數(shù)據(jù)庫的時候,多加一個參數(shù):
$pdo = new PDO($dsn, $username, $passwd, [PDO::ATTR_PERSISTENT => true]);
后面的PDO::ATTR_PERSISTENT => true 就是開啟長連接的方法。
2、長連接對nginx無效嗎
博主在搜索長連接相關知識的時候,看到一篇文章,結論是長連接僅適用于apache,不適用于nginx,這是真的嗎?
參考文章:http://www.dbjr.com.cn/article/133709.htm
大致結論是:長連接更多的是針對于apache的,因為apache維護一個進程池,開啟了apache mpm功能之后,apache會默認維持一個進程池,mysql長連接之后的連接,并沒有作為socet連接關閉,而是作為一個不釋放的東西,放進了進程池/線程池里面去。
而對于nginx來說,長連接是無效的,腳本執(zhí)行結束則釋放資源?
3、php-fpm下的長連接測試
這里前輩已經(jīng)測試過了,咱們給出前輩的地址,大家有興趣的可以看看
結論:
事實證明php-fpm是可以實現(xiàn)長連接的,只是如果該進程空閑的話,會造成資源浪費。
php-fpm的配置文件可以考慮設置pm.max_requests = 1000,代表每一個子進程的最大請求服務數(shù)量,如果超過了這個值,該子進程會被自動重啟。
比如max_requests這個參數(shù),如果設置很大的話,那這個子進程要運行很多次才會重啟,假如這個請求發(fā)生了錯誤或者內(nèi)存泄漏,那么這個值設置很大是不合適的。但如果請求沒有問題,這個值設置小的話就會頻繁的重啟,這樣也會碰到不少502的問題,所以要仁者見仁,智者見智的設置了,這里初始化設置1000,如果測試沒有內(nèi)存泄漏等問題,可以再大一些。
4、長連接對事務的影響
參考博文地址:https://www.zhihu.com/question/62603122
總結: 如果業(yè)務并發(fā)比較大且?guī)в惺聞?,不建議使用長連接的方式。
5、總結
博主在不斷的搜索中,發(fā)現(xiàn)長連接要發(fā)揮出最佳性能始終是避不開連接池這點的,而php恰恰又不能很好的實現(xiàn)連接池,這點確實是有點小遺憾。
整體來說在php中是暫時無法配置和mysql的完美連接池的,在業(yè)務比較復雜的地方,還是謹慎試用長連接,每個連接都是1個線程,會造成大量的資源浪費。
如果是某些業(yè)務需要持續(xù)的數(shù)據(jù)庫操作,比如提交日志接口等,那么是可以考慮打開長連接的,記得設置max_requests來定量關閉php-fpm連接,fpm關閉之后也會自動釋放mysql的連接。
還有pm.max_spare_servers設置服務器空閑時最大php-fpm進程數(shù)量。
例如: pm.max_spare_servers = 25 如果空閑時,會檢查進程數(shù),多于25個了,就會關閉幾個,達到25個的狀態(tài)。
擅長swoole的同學,可以參考這篇文章:
基于swoole擴展實現(xiàn)真正的PHP數(shù)據(jù)庫連接池
四、pdo部分demo的封裝
首先這部分博主是參考了一個網(wǎng)友的封裝,github地址如下:
https://github.com/nadirvishun/php-pdo-class
這個網(wǎng)友基本的增刪改查都封裝好了,而且都有參數(shù)預處理,安全性還是可以的。不過既然作為一個基準的類,還是缺少一些東西。
1、斷線重連機制
例如重連函數(shù):
/** * @params:重連函數(shù),上限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->setAttribute(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根本就捕獲不到,所以博主這里自定義錯誤處理函數(shù)來處理。
這部分是轉化php的warnings錯誤為try..catch可以捕獲的error錯誤,關于php的報錯機制以及錯誤處理這塊,咱們下篇再討論。
//自定義warnings處理函數(shù)set_error_handler('customException');//拿到warnngs錯誤之后,轉化為error錯誤拋出,這樣就可以被try..catch捕獲function customException( $error_no, $error_msg, $error_file, $error_line){ throw new \Exception($error_msg,0,null); //throw new \Exception($error_msg);}
3、析構方法回收資源
/** * destruct 關閉數(shù)據(jù)庫連接 */ 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長連接的優(yōu)缺點總結的文章就介紹到這了,更多相關php封裝pdo實例及pdo長連接優(yōu)缺點分析內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
PHP持久連接mysql_pconnect()函數(shù)使用介紹
mysql_pconnect()函數(shù)可以大大的提高MYSQL效率,不過,此連接不自動關閉,也會造成一些問題,請注意將不用的連接即時關閉,以避免不必要的錯誤發(fā)生2012-02-02PHP中file_exists與is_file,is_dir的區(qū)別介紹
很顯然file_exists是受了asp的影響,因為asp不但有fileExists還有folderExists,driverExists,那么PHP中file_exists是什么意思呢2012-09-09