2010年2月22日 星期一

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。

2 則留言:

  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.

    回覆刪除

在 Fedora 下裝 id-utils

Fedora 似乎因為執行檔撞名,而沒有提供 id-utils 的套件 ,但這是使用 gj 的必要套件,只好自己編。從官網抓好 tarball ,解開來編譯 (./configure && make)就是了。 但編譯後會遇到錯誤: ./stdio.h:10...