核心差異
| 特性 | mysql_connect (短連接) | mysql_pconnect (長連接/持久連接) |
| 生命週期 | 腳本啟動建立,結束自動關閉 | 首次建立後常駐進程池,腳本結束不關閉 |
| 復用機制 | 無,每請求新建 | 同進程池內復用相同連結資源 ID |
| 適用場景 | 低併發、PHP-FPM 模式、無狀態服務 | 高併發、Apache Prefork MPM、長連線業務 |
| 資源風險 | 頻繁建連開銷大 | 易耗盡 MySQL max_connections、殘留鎖/臨時表/事務 |
為什麼現代 PHP 棄用 mysql_pconnect?
- PHP-FPM 架構:每請求獨立進程,進程結束連接自動斷,長連接無法跨進程復用,反而佔用資源。
- 連接洩漏風險:未提交事務、未釋放鎖表 (
LOCK TABLES)、臨時表殘留、Session 變量污染,下一請求繼承髒狀態。
- Apache Prefork 唯一受益場景:父進程 fork 子進程時複製連接句柄,但受限於
max_connections,高併發極易打滿。
- 驅動層面:
ext/mysql 已在 PHP 7.0 移除,mysqli / PDO 僅支援短連接(mysqli::real_connect、PDO::ATTR_PERSISTENT 同樣有上述風險)。
正確的高併發連接策略:連接池
- 應用層連接池:PHP 不適合,建議 Java/Go 微服務層做池化。
- 中間件代理:
ProxySQL、MySQL Router、MaxScale 維護連接池,PHP 短連接代理,後端長連複用。
- PHP 端優化:
mysqli::persistent 僅在 CLI 長運行腳本 (Worker/Queue Consumer) 有價值,Web-FPM 禁用。
遷移建議
// 舊代碼
$link = mysql_pconnect('host','user','pass');
// 新代碼 (PDO + 預處理)
$pdo = new PDO('mysql:host=host;dbname=db;charset=utf8mb4', 'user', 'pass', [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
]);
// 短連接,請求結束自動回收,無殘留狀態
總結
短連接 + 連接池中間件 = 現代高併發 PHP 架構正解。mysql_pconnect 是上世紀產物,請從代碼庫中徹底移除。