現象:Error Log 出現
[Warning] IP address '10.0.0.220' could not be resolved: Name or service not known
根因:MySQL 連線建立時的主機名解析流程
- 新連線 → 產生執行緒處理
- 檢查 Host Cache (主機名快取) 是否已有該 IP 記錄
- 無快取 → 呼叫系統
gethostbyaddr(IP) 解析主機名
- 再呼叫
gethostbyname(主機名) 解析回 IP,雙向驗證一致性
- 若 OS 支援 thread-safe 版本 (
gethostbyaddr_r/gethostbyname_r) 則優先使用,否則加互斥鎖串行解析
- 結果存入 Host Cache,後續同 IP 直接命中
/etc/hosts 解析優先順序實驗證明
MySQL 以 IP 為唯一鍵,解析 /etc/hosts 時只取第一個匹配的主機名,後續同 IP 的主機名記錄被忽略。
# /etc/hosts
192.168.1.1 hostname_online
192.168.1.1 h_tt_1
# MySQL 解析結果:192.168.1.1 → hostname_online (第一筆)
# h_tt_1 永遠不會被解析使用
驗證步驟:
GRANT USAGE ON *.* TO root@'h_tt_%' IDENTIFIED BY 'root';
FLUSH HOSTS; 清空快取
- 客戶端
mysql -h 192.168.1.1 -u root -proot → 拒絕 (解析為 hostname_online)
- 調換 /etc/hosts 順序,
FLUSH HOSTS; 再測 → 成功 (解析為 h_tt_1)
關鍵配置參數
| 參數 | 作用 | 建議 |
| skip_name_resolve | ON=禁用 DNS 解析,權限表只能用 IP/% | 生產環境 建議 ON,消除 DNS 延遲與失穩 |
| skip_host_cache | ON=禁用 Host Cache,每次連線即時解析 | 通常 OFF,快取命中率高 |
| host_cache_size | Host Cache 條目上限 (預設 128/256) | 高併發大量客戶端 IP 可調大 (如 1024) |
| skip_networking | ON=禁用 TCP/IP,僅允許 Socket | 極高安全需求時啟用 |
管理指令
# 查看 Host Cache 內容 (MySQL 5.7+)
SELECT * FROM performance_schema.host_cache;
# 手動清空 Host Cache
FLUSH HOSTS;
# 或
mysqladmin flush-hosts
效能優化策略
- 啟用 skip_name_resolve=ON:權限表改用 IP/%,杜絕 DNS 依賴,連線建立零解析延遲
- 調大 host_cache_size:
SET GLOBAL host_cache_size=2048; (需 5.7.5+),減少解析頻率
- 維護 /etc/hosts:內網主機少量時,手動維護 IP-主機名映射,比 DNS 穩定
- 避免同 IP 多主機名:/etc/hosts 每 IP 僅保留一行,順序決定解析結果
- 監控 Host Cache 命中率:
performance_schema.host_cache 觀察 COUNT_IP、COUNT_HOST
適用環境決策樹
IF 內網主機固定且可控:
採用 /etc/hosts + skip_name_resolve=ON
ELSE IF 有可靠內部 DNS 且主機量大:
關閉 skip_name_resolve, 調大 host_cache_size
ELSE IF 雲環境/動態 IP/容器化:
僅用 IP/% 權限, skip_name_resolve=ON, 服務發現註冊 IP
ELSE:
預設配置, 監控 Warning 日誌頻率
總結
MySQL 主機名解析採用 IP 為鍵、雙向驗證、快取優先、只取 /etc/hosts 第一匹配 機制。生產環境強烈建議 skip_name_resolve=ON,權限表統一用 IP/%,徹底消除 DNS 解析帶來的延遲、失敗與安全風險。搭配 host_cache_size 調優與 FLUSH HOSTS 運維,可構建穩定高效的連線建立路徑。
- 上一篇文章: MySQL 實用小技巧持續更新:隨機抽樣、分組統計、常用函數、去重、大量匯入優化
- 下一篇文章: SSH 隧道安全訪問 MySQL 完整實戰:本地端口轉發、Navicat 配置、常駐服務化
Copyright ©
程式碼之家 All Rights Reserved