接続トラブルの犯人を追う!

接続トラブルの犯人を追う!

NTT オープンソースソフトウェアセンタ 板垣 貴裕

 

PostgreSQL をきちんと設定をしたつもりでも、予想もしない原因で上手く動作しない場合があります。 本記事では、実際にユーザ会メーリングリストに投稿された事例を元に、PostgreSQLのトラブルシュートの手順を追ってみます。 接続トラブル時の調査の仕方に加えて、原因を見つけて貰いやすいトラブル報告の仕方を考えます。

状況

「接続エラー」という件名でメーリングリストにトラブルが報告されました。 この際、単にトラブルの有無だけでなく、使用環境と発生状況も記されていました。

使用環境は以下ということでした。

また、発生状況も正確に報告されました。

  • インストールしたマシンでは、psql コマンドでは接続できる。
  • 他のLinuxマシンから接続を試みると次のエラーが出る。
    $ psql --host=hostname username
    psql: server closed the connection unexpectedly
            This probably means the server terminated abnormally
            before or while processing the request.
  • Python で接続しようとすると、下記のようなエラーになる。
    postgresql.exceptions.ClientCannotConnectError:
      failed to establish connection to server
      CODE: 08001
      LOCATION: CLIENT
      CONNECTION: [failed]
      failures[0]:
        NOSSL socket('127.0.0.1', 5432)
        postgresql.exceptions.ProtocolError:
          server did not support SSL negotiation
          CODE: 08P01
          LOCATION: CLIENT
          HINT: The server is probably not PostgreSQL.
      failures[1]:
        socket('127.0.0.1', 5432)
        postgresql.exceptions.ConnectionFailureError:
          unexpected EOF from server
          CODE: 08006
          LOCATION: CLIENT
          DETAIL: Zero-length read from the connection's socket.

後から考えると、この際に PostgreSQL のサーバログに何が出力されているかを聞いておくべきでした。 エラーの際は、クライアントへエラーが返されるだけでなく、サーバ側のログにも記録されます。 それを見比べることをしていれば、もう少し早く正解にたどり着けたかもしれません。

よくある症状を元に聞き取り

ここから、メーリングリストの購読者の間で、原因の調査が始まりました。 接続は比較的よくあるトラブルなので、まずはよくある症状に該当しないかの聞き取りが始まりました。

まず最初に疑ったのは、py-postgresql 接続ドライバが出力している "server did not support SSL negotiation" メッセージでした。SSL 接続が上手くいっていないのでしょうか?

しかし、--with-openssl でサーバを再構成してもらっても、上手くいきませんでした。

次に、psql でも接続できていないようなので、PostgreSQL サーバ自体が疑わしいということになりました。ローカルからは接続できるため、ネットワーク関係の設定を確認してもらいました。

  • ファイアウォールが 5432 ポートを塞いでいないか?
  • listen_addresses の設定は変更しているか?
  • pg_hba.conf の設定を変更しているか?

しかし、どれもきちんと設定済みということでした。

新情報から容疑者を絞り込む

ここで、新しい情報が届きました。

  • ローカルからの接続であっても、localhost ではなくホスト名を指定するとエラーになる。
  • サーバログに以下のメッセージが記録されていた。
    LOG:  could not bind IPv4 socket: アドレスは既に使用中です
    HINT:  Is another postmaster already running on port 5432?
           If not, wait a few seconds and retry.

サーバログのメッセージが最大の決め手になりました。 このメッセージは、ポート番号 5432 を他のプロセスが使用しているため、5432 ポートで接続を待ち受けられないという旨のエラーです。 実際、PostgreSQL のポートを変更して再起動すると、接続できたということでした。

$ psql --port=9999

その後の報告によると、5432 ポートはなぜか別のバックアップ・ソフトウェアが使っていたということでした。その調査には lsof コマンドが活躍したそうです。

トラブルを解消するには

トラブルをすばやく解くには、十分な情報提供が必要です。 本件では比較的多くの情報が提供されたため、解決にうまく結びついたようです。

一般論ですが、トラブル報告の際に心掛けるとスムーズな解決が望める項目を以下に挙げます:

適切な件名(サブジェクト)
メーリングリストへの投稿の際は、問題を的確に表す件名にすると良いでしょう。本件では「接続エラー」という明確な件名でした。もしこれが「助けて~」や「PostgreSQLで 問題発生」などであれば、回答者の気を引くことができなかったかもしれません。
環境
環境やバージョンは非常に重要です。特定の環境や古いバージョンのみで発生する不具合があるかもしれないからです。ただ、使っているバージョンがあまりに古いと「先に最新版で試してみたら?」と返されてしまうかもしれません。普段からアップデートに追従するよう心掛けましょう。
クライアントとサーバの両方のエラーメッセージ
本件では、クライアント側のメッセージは提示されましたが、サーバ側がありませんでした。もしサーバ側のエラーメッセージも確認できていれば、もっと短い時間でトラブルが解消できたかもしれません。その際には、実際に出力されたメッセージを使って伝えましょう。「エラーになりました」などと省略はせずに、むしろコピー&ペーストで構いません。
既に試したこと、既に行った設定
回答する際に迷うのが、問合せしたユーザが本当に初心者なのか、それとも既に自分で問題を解こうと試してみたのか、ということです。初心者向けの基本的な項目の確認をスキップして良いのであれば、それを明記したほうがスムーズに本題に入れます。

PostgreSQL はオープンソース・ソフトウェアであり、コミュニティのサポートもあくまでボランティア・ベースです。とは言え、問題の報告が適切であれば、多くのトラブルに対する回答は貰えているようにみえます。自分で調べても良くわからない問題は、気軽に質問してみましょう。そのやり取りは、次にその問題で困った人の役にも立つはずです。

外部リンク


(2009年12月10日 公開)