MySQL 建立連線時會延遲一下

最近用 Python 的 MySQLdb 連線忽然會卡個五秒才完成, 一路試的結果, 發現五秒鐘全用在 new _mysql.connection。改用一般的 mysql client 試, 也會卡五秒, 才發現問題出在 MySQL server。這和之前登入 SSH 時會延遲一下是同樣狀況, 連本機沒問題, 連另一台就會出問題。

參照《How MySQL Uses DNS》的說法, 即使連 IP, MySQL server 也會查 DNS。若沒設好 IP 反查, 就會卡個一陣子繼續。有兩種簡單解法:
  1. 如官網所言, 重跑 mysqld, 加上 --skip-name-resolve
  2. 在 mysqld 執行的 server 上, 在 /etc/hosts 裡幫 client 所在的 IP 隨便加筆記錄。如 client IP 為1.2.3.4 就加上:

    1.2.3.4 myhost.org.tw myhost
    這樣就不會去問 DNS 等個五秒才放棄。
以下是較不相關的碎碎念。
man page 說設好 /etc/hosts 後應該會立即生效, 除非是程式有設 cache。我試的結果是, host、nslookup 都沒反應, 確認過 /etc/nsswitch.conf、/etc/host.conf 都說會先查 /etc/hosts 才查 DNS, 搞不清楚為啥 (也不知道到底是以 nsswitch.conf 還是以 host.conf 為準)。後來乾脆用 C network API (gethostbyaddr) 直接查, 藉此確認我有設對 /etc/hosts.conf。原以為可以秒殺, 結果寫寫一堆問題。用 C coding 真麻煩, 後來改用 Python 瞬間搞定:
import socket
print socket.gethostbyaddr('127.0.0.1')

2010-02-22 更新

Scott 說明才知道 host 和 nslookup 不會查 /etc/hosts, 將他的留言直接貼進來:
This is a common problem that newbies run into. Answer: host(1) and nslookup(1) does not call gethostbyname(3) or the IPv6 safe getnameinfo(3) but issue DNS requests directly.

What you want is getent(1) from glibc:

getent hosts 127.0.0.1
查 man host 才發現, 文中沒有提到 /etc/hosts 啊!! 而 man gethostbyname, gethostbyaddr 才有提到 /etc/host.conf 和 /etc/hosts。

留言

  1. This is a common problem that newbies run into. Answer: host(1) and nslookup(1) does not call gethostbyname(3) or the IPv6 safe getnameinfo(3) but issue DNS requests directly.

    What you want is getent(1) from glibc:
    getent hosts 127.0.0.1

    回覆刪除
  2. Oops. No wonder the man page only mentions /etc/resolv.conf.

    回覆刪除

張貼留言

這個網誌中的熱門文章

(C/C++ ) 如何在 Linux 上使用自行編譯的第三方函式庫

熟悉系統工具好處多多

virtualbox 使用 USB 裝置