MySQL 客戶端連線時,是否指定 -h 參數決定連線協議,進而決定伺服器端看到的來源主機名:
-h 參數(或 -h localhost)→ Unix Socket 連線 → 伺服器端來源主機名為 localhost-h 127.0.0.1 → TCP/IP 連線 → 伺服器端來源主機名為 127.0.0.1MySQL 權限表 mysql.user 中 Host 欄位存儲允許連線的主機名。連線建立時,伺服器以「來源主機名」匹配 Host 欄位:
Host='localhost' 的帳號Host='127.0.0.1' 或 Host='%' 的帳號常見坑點:僅建立 'root'@'localhost' 帳號,卻用 mysql -h 127.0.0.1 -u root -p 連線 → 拒絕存取(找不到匹配帳號)。
| 設定 | TCP/IP 連線 (127.0.0.1) | Socket 連線 (localhost) | 說明 |
|---|---|---|---|
| OFF (預設) | 解析 IP → 主機名 → 通常為 localhost | localhost | 兩者最終 current_user 均為 root@'localhost' |
| ON | 不解析,直接用 127.0.0.1 | localhost | current_user 分別為 root@'127.0.0.1'、root@'localhost' |
skip_name_resolve=ON 可避免 DNS 解析延遲,但權限表必須使用 IP 或 %,不再支援主機名。
CREATE USER 'app'@'localhost' IDENTIFIED BY 'pwd'; CREATE USER 'app'@'127.0.0.1' IDENTIFIED BY 'pwd'; GRANT ALL ON mydb.* TO 'app'@'localhost', 'app'@'127.0.0.1';
CREATE USER 'app'@'%' IDENTIFIED BY 'pwd';
skip_name_resolve=ON,權限表統一用 IP,消除 DNS 依賴與解析延遲。host=127.0.0.1 強制 TCP/IP,避免 Socket 檔案權限/路徑問題。-- 查看當前連線的實際帳號 SELECT CURRENT_USER(); -- 查看權限表內容 SELECT User, Host FROM mysql.user WHERE User='root'; -- 測試兩種連線方式 mysql -u root -p # Socket → localhost mysql -h 127.0.0.1 -u root -p # TCP/IP → 127.0.0.1
localhost 與 127.0.0.1 在 MySQL 中不是同義詞,分別代表 Unix Socket 與 TCP/IP 兩種截然不同的連線協議。理解此機制、正確配置權限帳號、善用 skip_name_resolve,是避免「明明密碼正確卻連不上」經典問題的關鍵。