接続トラブルの犯人を追う!
NTT オープンソースソフトウェアセンタ 板垣 貴裕
PostgreSQL をきちんと設定をしたつもりでも、予想もしない原因で上手く動作しない場合があります。 本記事では、実際にユーザ会メーリングリストに投稿された事例を元に、PostgreSQLのトラブルシュートの手順を追ってみます。 接続トラブル時の調査の仕方に加えて、原因を見つけて貰いやすいトラブル報告の仕方を考えます。
状況
「接続エラー」という件名でメーリングリストにトラブルが報告されました。 この際、単にトラブルの有無だけでなく、使用環境と発生状況も記されていました。
使用環境は以下ということでした。
- RHEL-5 (SELinux disabled)
- PostgreSQL-8.4.1
- Python-3.1.1
- py-postgresql-0.9.1
また、発生状況も正確に報告されました。
- インストールしたマシンでは、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 はオープンソース・ソフトウェアであり、コミュニティのサポートもあくまでボランティア・ベースです。とは言え、問題の報告が適切であれば、多くのトラブルに対する回答は貰えているようにみえます。自分で調べても良くわからない問題は、気軽に質問してみましょう。そのやり取りは、次にその問題で困った人の役にも立つはずです。