同樣是本機連接,為什麼 localhost 失敗而 127.0.0.1 成功?本文深入解析 Unix Domain Socket 與 TCP 連接的差異、常見故障場景、多種修復方案與最佳實踐配置。
| 主機參數 | 傳輸協議 | MySQL 端處理 | 適用場景 |
|---|---|---|---|
localhost | Unix Domain Socket (檔案) | 讀取 mysql.sock 路徑 | 同機、高效能、低延遲 |
127.0.0.1 | TCP/IP (回環介面) | 監聽 3306 端口 | 跨容器、Docker、強制 TCP |
::1 (IPv6) | TCP/IPv6 | 監聽 IPv6 端口 | IPv6 環境 |
Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)
datadir 變更導致路徑不一致php.ini 的 mysqli.default_socket / pdo_mysql.default_socket 指向錯誤路徑mysql -e "SHOW VARIABLES LIKE 'socket';"
# 或
cat /etc/my.cnf | grep socket
php.ini):
[MySQLi]
mysqli.default_socket = /var/run/mysqld/mysqld.sock
[PDO_mysql]
pdo_mysql.default_socket = /var/run/mysqld/mysqld.sock
systemctl restart php-fpm代碼層面指定主機為 127.0.0.1:
$mysqli = new mysqli('127.0.0.1', 'user', 'pass', 'db', 3306);
$pdo = new PDO('mysql:host=127.0.0.1;dbname=db;port=3306', 'user', 'pass');
或全域配置 my.cnf 強制 TCP:
[mysqld]
protocol = TCP
skip-networking = 0
bind-address = 127.0.0.1
ln -sf /var/run/mysqld/mysqld.sock /tmp/mysql.sock
# 或反向,視實際路徑而定
再設 mysqli.default_socket = /tmp/mysql.sock
# 臨時關閉驗證
setenforce 0
# 或調整策略
ausearch -c 'php-fpm' --raw | audit2allow -M php-fpm-mysql
semodule -i php-fpm-mysql.pp
mysql:3306)而非 localhost-p 3306:3306,用 127.0.0.1host.docker.internal:3306 (Docker Desktop) 或宿主機真實 IP<?php
$mysqli = new mysqli('localhost', 'root', 'pass', 'test');
if ($mysqli->connect_errno) {
echo "失敗: " . $mysqli->connect_error;
} else {
echo "成功,連接 ID: " . $mysqli->thread_id;
echo "協議: " . $mysqli->protocol_version; // 10 = socket, 其他 = TCP
$mysqli->close();
}
?>
127.0.0.1,避免 socket 路徑不一致問題,便於容器化遷移localhost補充:Windows 平台無 Unix Socket,
localhost會自動解析為 TCP 連接,不存在此問題。跨平台部署時請注意此差異。