他們說
他們說,pdo連接持久化后持有相同憑證的請求可以使用原來的連接,
從而避免反復創建和關閉連接帶來的耗時,
而且,操作上非常方便,
只要在創建pdo對象的時候,
指定PDO::ATTR_PERSISTENT => true就可以了,
這么好,
我也要試下
並沒有
首先,我們先看下已有的數據庫連接,
這是我本地的navicate產生的連接,后面對比的時候,需要排除這兩個連接,
接着,使用持久連接的方式創建一個pdo對象,並執行下查詢操作,
通過cli模式來運行腳本,
連接成功,看下連接還在不在,
結果並沒有新增連接,也就是說,連接並沒有被持久化,
嗯。。。。。。。。。。
貌似我們的打開方式有點問題,
仔細一想,連接要想持久化,必須寄生在一個常駐進程中,
而php腳本運行到結束后,php進程就結束了,
所以持久化肯定不是在php進程中進行的,
那難道是pdo自己產生了常駐的進程來維持連接?
通過對比運行前后的進程,
也並沒有發現新的進程產生。。。。。。
需要常駐的進程
無意間了看到了有人在fpm模式下使用pdo長連接的文章,
突然明白了,
fpm不就是常駐的進程嗎,
pdo連接在fpm中產生,並隨着當前fpm進程的結束而銷毀
不求同年同月同日生,但求同年同月同日死,
說的就是他們的關系。
再次實驗,還是一樣,先觀察已有的連接,
和上圖一樣,就不放圖了,
接着,為了使用fpm方式運行php腳本,
我們將腳本寫成接口的形式,從瀏覽器訪問該接口,
nginx收到請求后將請求轉發給某個fpm進程,
在fpm進程中運行php腳本,
腳本運行結束后,php進程退出,
但是fpm進程不會退出,
也因此,pdo對象得以保留
出現了新的連接!連接終於被保留下來了!
一個fpm進程一個連接
刷新瀏覽器,再次請求接口時,
又多了一個新的數據庫連接!
再刷新一次,又多了一個連接!
不是說持久化連接可以被復用的嗎?
現在連接是持久化了,但是並沒有被復用啊!
這么搞,由於連接一直沒有被銷毀,mysql連接很快就會被耗盡!
再仔細想想,
連接對象是保留在fpm進程中的,
理論上,如過該fpm進程已經有了持久化的pdo對象,應該不會再去創建新的pdo對象了,
難道是,其他的fpm進程創建的?
當前有3個fpm進程與mysql建立了連接,
再一次通過瀏覽器發出請求,
果然,出現了新的fpm進程,並創建了新的連接!
連接復用了嗎?
我們修改fpm的配置文件,將子進程數設為靜態,並且最大值為1,防止fpm-master動態創建子進程,
看下當前的mysql連接情況,發現只有mysql一個人孤獨的監聽在3306端口上(navicate因為長時間沒有操作,連接斷開了)
通過瀏覽器發起一次請求,
可以看到有連接產生,
再次發起請求,
還是同樣的連接,
由於fpm子進程數只有1個,且不會動態增加,因此也不會產生新的連接,
連接終於被復用了!
總結
1.連接需要寄生在進程中, 要想維持長連接必須要有常駐的進程作為承載
2.在fpm模式下使用pdo長連接,一定要控制fpm進程數量小於mysql最大連接數,否則mysql連接數會被耗盡!