許多開發者遇過這種詭異情況:PHP 用 localhost 連 MySQL 失敗,改成 127.0.0.1 卻秒連。命令列 mysql -h localhost 也報錯,但 mysql -h 127.0.0.1 正常。權限、防火牆、服務狀態皆無問題。
| 連線方式 | 主機標識 | 傳輸協議 | MySQL 權限匹配 |
|---|---|---|---|
| TCP/IP | 127.0.0.1 / 實際 IP | 網路埠 (預設 3306) | user@'127.0.0.1' 或 user@'%' |
| Unix Socket | localhost | 本地檔案 Socket (/var/run/mysqld/mysqld.sock) | user@'localhost' |
關鍵點:MySQL 內部將 localhost 硬編碼為 Socket 連線,127.0.0.1 則走 TCP。兩者權限獨立,Socket 路徑若不一致即連線失敗。
mysqld --verbose --help | grep -i socket
# 輸出範例:socket /var/run/mysqld/mysqld.sock
; 找到並修改
mysql.default_socket = /var/run/mysqld/mysqld.sock
mysqli.default_socket = /var/run/mysqld/mysqld.sock
pdo_mysql.default_socket = /var/run/mysqld/mysqld.sock
修改後:
systemctl restart php-fpm 或 service php7.4-fpm restart。php -r "new PDO('mysql:host=localhost;dbname=test', 'user', 'pass'); echo 'OK';"
Windows 無 Socket 機制,localhost 經解析走 TCP。若報 ERROR 2003 (HY000): Can't connect ... (10061),請檢查:
net start mysql 或服務管理器啟動。my.ini 是否有 skip-networking 或 bind-address=127.0.0.1 限制。若不想折騰 Socket,應用層統一改用 127.0.0.1 最省心:
mysql:host=127.0.0.1;dbname=testuser@'127.0.0.1' 或 user@'%'理解協議差異,連線問題迎刃而解。