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

PHP PDO 連接報錯 SQLSTATE[HY000] [2002] No such file or directory:mysql.sock 路徑不匹配徹底解決

     編輯:PHP 相關知識

經典報錯:

Connection failed: SQLSTATE[HY000] [2002] No such file or directory

**本質:PHP PDO 尋找 MySQL Unix Socket (`mysql.sock`) 路徑與 MySQL 實際生成路徑不一致。** 常見於 macOS (Homebrew/MySQL 官方 pkg)、XAMPP、多 MySQL 實例共存環境。


核心原理

  • PDO DSN `mysql:host=localhost` **強制使用 Unix Socket** (非 TCP)。
  • PHP 讀取 `php.ini` 中 `pdo_mysql.default_socket` (或 `mysqli.default_socket`、`mysql.default_socket`) 確定 socket 路徑。
  • MySQL 啟動時根據 `my.cnf` `[mysqld]` `socket=/path/mysql.sock` 生成文件。
  • **兩者路徑必須完全一致**,否則報 2002。

三步定位並修復

第一步:找到 MySQL 實際 socket 文件

# 方法 1:查詢運行中的 MySQL 進程
ps aux | grep mysqld
# 看啟動參數 --socket=/xxx/mysql.sock

# 方法 2:MySQL 客戶端查詢
mysql -u root -p -e "SHOW VARIABLES LIKE 'socket';"
# 輸出例:/tmp/mysql.sock  或  /var/lib/mysql/mysql.sock  或  /opt/homebrew/var/mysql/mysql.sock

# 方法 3:全盤搜索 (較慢)
sudo find / -name 'mysql.sock' 2>/dev/null

第二步:檢查 PHP 當前配置的 socket 路徑

php -i | grep 'default_socket'
# 輸出例:
# pdo_mysql.default_socket => /var/mysql/mysql.sock => /var/mysql/mysql.sock
# mysqli.default_socket => /var/mysql/mysql.sock => /var/mysql/mysql.sock
# mysql.default_socket => /var/mysql/mysql.sock => /var/mysql/mysql.sock

第三步:修改 php.ini 統一路徑並重啟

; 找到 php.ini 路徑
php --ini
; 輸出: Loaded Configuration File => /usr/local/php/etc/php.ini

; 編輯 php.ini,設置三個 socket 參數為第一步找到的真實路徑
; 例:實際為 /tmp/mysql.sock
pdo_mysql.default_socket = /tmp/mysql.sock
mysqli.default_socket = /tmp/mysql.sock
mysql.default_socket = /tmp/mysql.sock  ; 兼容舊 mysql_* 函數 (已棄用)

; 重啟 PHP-FPM / Apache
systemctl restart php-fpm
# 或
kill -USR2 `cat /usr/local/php/var/run/php-fpm.pid`

場景化解決方案

場景 1:macOS + Homebrew MySQL (最常見)

# Homebrew MySQL 默認 socket:/tmp/mysql.sock
# 但 PHP 預設常找 /var/mysql/mysql.sock

# 解決:建立軟連結 (最省事,無需改 php.ini)
sudo mkdir -p /var/mysql
sudo ln -s /tmp/mysql.sock /var/mysql/mysql.sock

# 或改 php.ini (推薦,顯式明確)
pdo_mysql.default_socket = /tmp/mysql.sock

場景 2:XAMPP / MAMP 集成環境

# XAMPP socket 通常在:
/Applications/XAMPP/xamppfiles/var/mysql/mysql.sock  (macOS)
/opt/lampp/var/mysql/mysql.sock                     (Linux)
C:\xampp\mysql\data\mysql.sock                      (Windows 無 socket 概念,用 TCP)

# php.ini 設置:
pdo_mysql.default_socket = /Applications/XAMPP/xamppfiles/var/mysql/mysql.sock

場景 3:Linux 多實例 / 自編譯 MySQL

# my.cnf 指定 socket
[mysqld]
socket = /data/mysql/3306/mysql.sock
port = 3306

[client]
socket = /data/mysql/3306/mysql.sock  # 客戶端默認連這個

# PHP 必須同步設置
pdo_mysql.default_socket = /data/mysql/3306/mysql.sock

場景 4:強制使用 TCP 繞過 Socket (通用臨時方案)

<?php
// DSN 使用 127.0.0.1 而非 localhost,強制走 TCP/IP (默認 3306 端口)
$dsn = "mysql:host=127.0.0.1;dbname=test;charset=utf8mb4";
// 或顯式指定端口
$dsn = "mysql:host=127.0.0.1;port=3306;dbname=test;charset=utf8mb4";

$pdo = new PDO($dsn, 'user', 'pass');
?>
**原理:** `localhost` 在 PDO/MySQL 客戶端庫中特殊處理為 Unix Socket;`127.0.0.1` 則解析為 TCP 連接。**生產環境建議顯式使用 `127.0.0.1` 避免 socket 路徑糾紛**,且便於後續遷移至雲數據庫/讀寫分離中間件。

驗證修復

php -r "
try {
    \$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
    echo 'Socket 連接成功';
} catch (PDOException \$e) {
    echo '失敗: ' . \$e->getMessage();
}
"

總結:避坑清單

  1. 優先用 `127.0.0.1` 走 TCP,消除 socket 路徑依賴。
  2. 必須用 `localhost`/Socket 時:**`php.ini` 三個 `default_socket` + MySQL `my.cnf` `socket` 四路統一**。
  3. 修改配置後**必須重啟 PHP 進程** (php-fpm/Apache mod_php)。
  4. Docker 環境:容器間通訊**只能用 TCP** (`host=mysql-container-name`),無共享 socket。

搞清「Socket vs TCP」與「配置四路統一」,2002 錯誤將不再出現。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved