在部署 LAMP/LNMP 環境時,常遇到 MySQL Client、PHP 擴展與資料庫服務對 Unix Socket 路徑認知不一致的問題。典型現象為:
/var/lib/mysql/mysql.sock/tmp/mysql.sockMySQL 編譯安裝時 --with-unix-socket-path 參數決定預設 Socket 路徑;而 PHP 編譯參數 --with-mysql-sock、--with-mysqli、--with-pdo-mysql 再次指定 Socket 路徑。若兩者編譯參數不同,或 my.cnf 中 [client]、[mysqld] 區塊的 socket 設定不一致,即會產生路徑分歧。
編輯 /etc/my.cnf(或 /etc/mysql/my.cnf),確保 [mysqld]、[client]、[mysql] 三區塊皆指向同一路徑:
[mysqld]
socket = /var/lib/mysql/mysql.sock
[client]
socket = /var/lib/mysql/mysql.sock
[mysql]
socket = /var/lib/mysql/mysql.sock
重啟 MySQL 服務:systemctl restart mysqld
若不想動編譯參數,可建立軟連結讓雙方路徑互通:
ln -s /var/lib/mysql/mysql.sock /tmp/mysql.sock
# 或反向
ln -s /tmp/mysql.sock /var/lib/mysql/mysql.sock
注意: 需確保 MySQL 進程對目標目錄有讀寫權限(通常屬於 mysql:mysql)。
在連線字串中顯式指定 unix_socket 參數,覆蓋預設值:
<?php
// mysqli 物件導向風格
$mysqli = new mysqli('localhost', 'root', 'password', 'dbname', 3306, '/var/lib/mysql/mysql.sock');
// PDO 風格
$dsn = 'mysql:unix_socket=/var/lib/mysql/mysql.sock;dbname=dbname';
$pdo = new PDO($dsn, 'root', 'password');
?>
<?php
$host = '127.0.0.1'; // 強制走 TCP 避開 Socket
$user = 'root';
$pass = '008';
$link = mysqli_connect($host, $user, $pass);
if (!$link) {
die('連線失敗: ' . mysqli_connect_error());
}
echo '連線成功!';
mysqli_close($link);
?>
關鍵提醒:
127.0.0.1 而非 localhost,強制走 TCP/IP 協議繞過 Socket 問題root@127.0.0.1 或 root@%firewall-cmd --add-port=3306/tcp --permanent# 檢查 MySQL 實際監聽的 Socket
mysqladmin variables | grep socket
# 檢查 PHP 編譯參數
php -i | grep -i socket
# 即時監控 Socket 檔案
ls -l /var/lib/mysql/mysql.sock /tmp/mysql.sock
生產環境建議採用 方案一 從源頭統一路徑,並將 Socket 檔案放置於 /var/lib/mysql/ 等持久化目錄,避免 /tmp 因系統清理導致 Socket 遺失。若歷史專案難以統一,可結合方案二(符號連結)與方案三(程式碼顯式指定)過渡兼容。
Linux 無盤啟動完整實作指南:基於 PXE、DHCP、TFTP 與 NFS
Linux 軟體 RAID 5 完整建立與管理實戰:從分區、建陣列到故障模擬與熱插拔
Linux 內核定製指南:依硬體精簡編譯、提升開機速度與釋放記憶體
Unix 系統程式設計實作:my_copy 檔案複製效能測試與 vmstat 監控分析
Linux 實戰技巧十則:虛擬控制台、滑鼠複製貼上、快速跳轉目錄、彩色 ls、指令定位、檔案搜尋、core 清理、mc 文件管理、後台 X 程式、強制退出 X
Linux 文件檢視與管理核心命令大全:cat、less、head、tail、touch、umask、chattr、find 實戰