首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

MySQL 無法通過 localhost 或 127.0.0.1 連線:Socket vs TCP 根因與修復

     編輯:MySQL 綜合教學

MySQL 無法通過 localhost 或 127.0.0.1 連線:Socket vs TCP 根因與修復

「本機能用 127.0.0.1 連線,卻用不了 localhost」或反過來,是 MySQL 連線最經典的坑。根因在於 MySQL 將 localhost 視為 Unix Socket 連線,127.0.0.1 視為 TCP/IP 連線,兩者權限、配置、檔案路徑完全獨立。本文系統診斷並給出雙向修復方案。

核心機制差異

連線方式主機標識傳輸協議權限表匹配關鍵配置
Unix Socketlocalhost本地檔案描述符User@'localhost'socket=/path/to/mysql.sock
TCP/IP127.0.0.1TCP 回環介面User@'127.0.0.1'port=3306, bind-address

場景一:localhost 連不上,127.0.0.1 正常

典型錯誤

Warning: mysql_connect(): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)

診斷步驟

  1. 確認 MySQL 服務運行:systemctl status mysql 或 ps aux | grep mysqld
  2. 查詢實際 Socket 路徑:
    mysqld --verbose --help 2>/dev/null | grep '^socket'
    # 輸出範例:socket /var/run/mysqld/mysqld.sock
  3. 檢查 PHP 配置 php.ini:
    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
  4. 重啟 PHP-FPM / Apache 生效:systemctl restart php7.4-fpm

常見原因

  • MySQL 編譯/安裝路徑與 PHP 預設路徑不一致(如編譯指定 --with-mysql-sock=/tmp/mysql.sock,但 PHP 預設讀 /var/lib/mysql/mysql.sock)。
  • 多實例環境下,my.cnf 的 [client] 區段未指定 socket,導致 mysql 命令列工具與 PHP 使用不同 Socket。
  • Socket 檔案權限問題:ls -l /var/run/mysqld/mysqld.sock 確保 mysql 用戶可讀寫,PHP 運行用戶(如 www-data)有目錄執行權限。

場景二:127.0.0.1 連不上,localhost 正常

典型錯誤

Warning: mysql_connect(): Can't connect to MySQL server on '127.0.0.1' (111 "Connection refused")

排查清單

  1. MySQL 是否監聽 TCP: netstat -ntlp | grep 3306 或 ss -ntlp | grep 3306。若無輸出,檢查 my.cnf:
    [mysqld]
    # 註釋或刪除
    # skip-networking
    bind-address = 0.0.0.0  # 或具體 IP,127.0.0.1 僅允許本機
    修改後 必須重啟 MySQL。
  2. 權限表是否有 127.0.0.1 帳號:
    SELECT User, Host FROM mysql.user WHERE User='root';
    -- 若無 'root'@'127.0.0.1',需建立:
    CREATE USER 'root'@'127.0.0.1' IDENTIFIED BY 'password';
    GRANT ALL PRIVILEGES ON *.* TO 'root'@'127.0.0.1' WITH GRANT OPTION;
    FLUSH PRIVILEGES;
  3. 防火牆/SELinux 阻擋:
    # CentOS/RHEL 7+
    firewall-cmd --permanent --add-port=3306/tcp
    firewall-cmd --reload
    
    # SELinux 典型錯誤日誌 /var/log/audit/audit.log
    # 臨時關閉驗證:setenforce 0
    # 永久:/etc/selinux/config 設 SELINUX=disabled 並重啟
    # 或精準放行:setsebool -P mysql_connect_any 1
  4. /etc/hosts 解析異常: 確保 127.0.0.1 localhost 存在且無衝突條目。

終極診斷大招:系統調用追蹤

# 追蹤 PHP 進程連線嘗試
strace -f -e trace=connect,open,stat php your_script.php 2>&1 | grep -E 'connect|mysql.sock'

# 追蹤 MySQL 進程接受連線
strace -p $(pidof mysqld) -e trace=accept,read,write 2>&1

可精準定位是 Socket 路徑錯誤、權限拒絕、還是 TCP 連線被拒。

最佳實踐建議

  • 應用程式配置統一使用 127.0.0.1,避免 Socket 路徑差異帶來的部署環境不一致。
  • 在 my.cnf [client] 區段明確指定 socket 路徑,命令列工具、PHP、Python 等客戶端均會讀取此配置。
  • Docker/K8s 環境強制使用 TCP(127.0.0.1 或 Service IP),Socket 僅用於 Sidecar 同 Pod 通訊。

核心口訣: localhost 走 Socket,127.0.0.1 走 TCP;權限分開配,路徑要對齊;防火牆 SELinux 別忘記。

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