首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 入門

PHP 連接 MySQL 完整指南:MySQLi vs PDO 深度比較、連線參數、錯誤處理與最佳實務

     編輯:PHP 入門

PHP 連接 MySQL 深度解析:雙介面架構差異、連線選項、連線池、安全配置與生產環境實戰

PHP 連接 MySQL 有兩大核心介面:MySQLi (MySQL Improved) 與 PDO (PHP Data Objects)。選擇正確的介面、配置最佳連線參數、實作健全錯誤處理,是資料庫應用穩定性的基石。本文系統性比較兩者架構、提供完整連線代碼模板、解析進階選項與最佳實務。

MySQLi vs PDO:核心架構差異

選擇建議

  • 新專案:強烈推薦 PDO — 現代、統一、可移植、例外導向
  • 純 MySQL 既有專案:MySQLi 可接受,但新模組建議 PDO
  • 需多資料庫支援:PDO 唯一選擇
  • 高併發異步需求:MySQLi async 或 Swoole/ReactPHP + PDO

標準連線代碼模板

MySQLi 物件導向 (含完整錯誤處理)

<?php
$host = 'localhost'; $port = 3306; $user = 'user'; $pass = 'pass'; $db = 'dbname';

$mysqli = @new mysqli($host, $user, $pass, $db, $port);
if ($mysqli->connect_errno) {
    // 生產環境記錄日誌,不輸出詳細錯誤給用戶
    error_log("MySQL 連線失敗 [{$mysqli->connect_errno}]: {$mysqli->connect_error}");
    throw new RuntimeException("資料庫連線失敗,請稍後再試");
}

// 設定字元集 (關鍵!)
$mysqli->set_charset('utf8mb4');

// 可選:設定時區
$mysqli->query("SET time_zone = '+00:00'");

// 可選:關閉自動提交 (交易控制)
$mysqli->autocommit(false);

return $mysqli;

MySQLi 程序式

$conn = @mysqli_connect($host, $user, $pass, $db, $port);
if (!$conn) {
    error_log("MySQL 連線失敗: " . mysqli_connect_error());
    throw new RuntimeException("資料庫連線失敗");
}
mysqli_set_charset($conn, 'utf8mb4');
mysqli_autocommit($conn, false);
return $conn;

PDO (生產環境標準配置)

<?php
$host = 'localhost'; $port = 3306; $db = 'dbname'; $user = 'user'; $pass = 'pass';
$charset = 'utf8mb4';

$dsn = "mysql:host=$host;port=$port;dbname=$db;charset=$charset";

$options = [
    PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,      // 例外模式
    PDO::ATTR_EMULATE_PREPARES   => false,                       // 真實預處理
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,            // 關聯陣列
    PDO::ATTR_STRINGIFY_FETCHES  => false,                       // 保持原生型別
    PDO::ATTR_PERSISTENT         => false,                       // 非持久連線 (見下文)
    PDO::MYSQL_ATTR_INIT_COMMAND => "SET time_zone = '+00:00'",  // 連線初始化指令
];

try {
    $pdo = new PDO($dsn, $user, $pass, $options);
    return $pdo;
} catch (PDOException $e) {
    error_log("PDO 連線失敗 [{$e->getCode()}]: {$e->getMessage()}");
    throw new RuntimeException("資料庫連線失敗,請稍後再試");
}

進階連線選項深度解析

持久連線 (Persistent Connections)

維度MySQLiPDO
支援資料庫僅 MySQL/MariaDB12+ (MySQL, PostgreSQL, SQLite, SQL Server, Oracle, ODBC...)
API 風格雙重:物件導向 + 程序式純物件導向
預處理語句原生支援,永真實預處理支援,預設模擬 (需關閉 ATTR_EMULATE_PREPARES)
錯誤處理手動檢查屬性/回傳值例外模式 (ERRMODE_EXCEPTION)
命名參數不支援 (僅 ? 位置)支援 (:name)
多重結果集支援 (next_result)不直接支援
異步查詢支援 (poll)不支援
學習曲線中等 (雙 API)低 (單一 OO API)
遷移成本高 (綁定 MySQL)低 (資料庫無關)

SSL/TLS 加密連線 (生產環境強制)

$options[PDO::MYSQL_ATTR_SSL_CA] = '/etc/ssl/mysql/ca.pem';
$options[PDO::MYSQL_ATTR_SSL_CERT] = '/etc/ssl/mysql/client-cert.pem';
$options[PDO::MYSQL_ATTR_SSL_KEY] = '/etc/ssl/mysql/client-key.pem';
$options[PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT] = true;
// DSN 不變,驅動自動協商 SSL

Unix Domain Socket (本機最高效能)

// PDO
$dsn = "mysql:unix_socket=/var/run/mysqld/mysqld.sock;dbname=$db;charset=$charset";

// MySQLi
$mysqli = new mysqli('localhost', $user, $pass, $db, 0, '/var/run/mysqld/mysqld.sock');

連線超時控制

// PDO (PHP 7.1+)
$options[PDO::ATTR_TIMEOUT] = 5; // 秒,連線階段超時

// MySQLi
$mysqli->options(MYSQLI_OPT_CONNECT_TIMEOUT, 5);

// 查詢超時需 SQL 層面設定
$pdo->exec("SET MAX_EXECUTION_TIME=30000"); // 毫秒,MySQL 5.7.8+

錯誤處理策略

特性說明
MySQLimysqli::real_connect(..., MYSQLI_CLIENT_PERSISTENT) 或 host 前綴 p:
PDOPDO::ATTR_PERSISTENT => true
優點重用連線,減少建立開銷
缺點連線狀態殘留 (交易、暫存表、變數)、達到 max_connections 限制、難以偵錯、PHP-FPM 工序模型下效益有限
建議生產環境預設關閉,僅極高頻短連線場景經壓測驗證後啟用

連線池與高併發架構

PHP 傳統模式 (PHP-FPM/Apache mod_php) 每請求建立連線,無內建連線池。高併發方案:

  1. PHP-FPM + 靜態/動態程序管理:調整 pm.max_children、pm.start_servers 匹配 DB max_connections
  2. 持久連線謹慎使用:配合 mysqli.rollback_on_cached_plink (PHP 8.1+)
  3. 應用層連線池:Swoole/OpenSwoole/RoadRunner + PDO 協程連線池
  4. ProxySQL:中介層連線池、讀寫分離、查詢重寫、快取
  5. 唯讀副本分流:主庫寫入、從庫讀取,應用層或 ProxySQL 路由

安裝驗證

<?php
// 檢查擴展載入
var_dump(extension_loaded('mysqli'));
var_dump(extension_loaded('pdo_mysql'));

// 檢查客戶端庫版本
echo "MySQLi client version: " . mysqli_get_client_info() . "\n";
$pdo = new PDO('mysql:host=localhost', 'user', 'pass');
echo "PDO MySQL client version: " . $pdo->getAttribute(PDO::ATTR_CLIENT_VERSION) . "\n";

總結

PHP 連接 MySQL 的核心決策:選 PDO、用例外模式、關閉模擬預處理、設定 utf8mb4、關閉持久連線、生產環境強制 SSL、統一錯誤處理層。MySQLi 保留給純 MySQL 既有專案或需異步/多重結果集的特殊場景。建立標準化連線工廠類別,封裝配置、重試、監控、審計,是專業 PHP 團隊的基本功。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
策略MySQLiPDO
開發環境mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT) 啟用例外ERRMODE_EXCEPTION (預設建議)
生產環境try-catch 包裝、自定義例外層級、記錄完整堆疊、用戶端顯示通用訊息同左
死鎖/鎖等待重試捕獲錯誤碼 1213/1205,指數退避重試 (最多 3 次)捕獲 SQLSTATE HY000/40001,同左
連線中斷重連ping() 檢測、重新建立連線、重試邏輯封裝同左