質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.50%

  • PHP

    24011questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

  • PostgreSQL

    1354questions

    PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

PHPの集計プログラムでPostgreSQLのログにConnection reset by peerと表示されて完走しないままプロセスが残留してしまう

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 676
退会済みユーザー

退会済みユーザー

前提・実現したいこと

PHP(5.2.17)+PostgreSQL(8.4.20)で集計のプログラムを作成しています。

cronによって定期実行させている、
幾つかの集計クエリーを実行して終了するバッチプログラムで、
サブクエリのあるINSERTや集計前のデータクリアの為のDELETE等、
時間がかかるクエリーの実行が有ると
まれにDB側にメッセージを残して処理が途中で停止し、
バッチプログラムのプロセスが残りっぱなしになる事が有るので
必ず完走させることが目的となります。

宜しくお願い致します。

2018.12.20 追記
トランザクションの分割を行い2日程動かしました。
現状では完走しないケースがまだ有りますが、
対応後で、若干エラー内容は変わりました。
一旦時間がかかるクエリーを個別にチューニングして様子を見ています。
Dec 20 01:02:51 [4191-1] LOG:  could not send data to client: Broken pipe
Dec 20 01:02:51 [4192-1] LOG:  unexpected EOF on client connection
Dec 20 01:02:51 [4193-1] LOG:  disconnection: session time: 0:02:49.872 user=ユーザー database=データベース host=ホスト port=ポート

2018.12.21 追記
トランザクションの分割のみでは結果が同じ模様。
引っかかった物からクエリーチューニングを行っているが、
難航中。(自由に実行、集中して作業が出来ないのが辛い所)

発生している問題・エラーメッセージ

PostgreSQL側に以下のメッセージが表示されます。

LOG:  could not receive data from client: Connection reset by peer
LOG:  unexpected EOF on client connection
LOG:  disconnection: session time: 0:02:51.973 user=USER database=DATABASE host=HOST port=PORT

該当のソースコード

【初回質問時(パターンA)】
$con = new PDO(DSN, USERNAME, PASSWORD);
$con->begin();
$con->exec($delete_sql1, $where); //集計テーブルクリア
$con->exec($delete_sql2, $where); //集計テーブルクリア
$con->exec($delete_sql3, $where); //集計テーブルクリア
//<<---↑このクエリに時間がかかった場合はログがここまでになる
$con->exec($insert_sql1, $where); //集計テーブルへ集計データを挿入
$con->exec($insert_sql2, $where); //集計テーブルへ集計データを挿入
$con->exec($insert_sql3, $where); //集計テーブルへ集計データを挿入
$con->commit();

【トランザクション分割(パターンB)】
$con = new PDO(DSN, USERNAME, PASSWORD);
$con->begin();
$con->exec($delete_sql1, $where); //集計テーブルクリア
$con->commit();
$con->begin();
$con->exec($delete_sql2, $where); //集計テーブルクリア
$con->commit();
$con->begin();
$con->exec($delete_sql3, $where); //集計テーブルクリア
//<<---↑このクエリに時間がかかった場合はログがここまでになる
$con->commit();
$con->begin();
$con->exec($insert_sql1, $where); //集計テーブルへ集計データを挿入
$con->commit();
$con->begin();
$con->exec($insert_sql2, $where); //集計テーブルへ集計データを挿入
$con->commit();
$con->begin();
$con->exec($insert_sql3, $where); //集計テーブルへ集計データを挿入
$con->commit();

試したこと

【パターンA時】
PHP側に
set_time_limit(0);
ini_set("session.gc_maxlifetime", 60*30);
を入れてみましたが改善できませんでした。

【パターンB時】
トランザクションを分割しました。

補足情報(FW/ツールのバージョンなど)

PHP(5.2.17)
PostgreSQL(8.4.20)

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

+2

困ったときの stackoverflow
WHERE句や、バインド文字が長いとおきる模様

How to debug could not receive data from client: Connection reset by peer - StackOverflow

down vote
accepted
I know this is an older post, but I just found it because I had the same error today in my postgres logs. I narrowed it down to a PDO select statement. I'm using Zend Framework 1.10.3 on Ubuntu Precise.

The following pdo statement generated an error if $opinion is a long text string. The column opinion is type Text in my postgres table. The query succeeds if $opinion is under a certain number of characters. 1000 characters works fine. 2000 characters fails with "could not receive data from client: Connection reset by peer".

  $select = $this->db->select()
           ->from( 'datauserstopics' )
           ->where("opinion = ?",trim($opinion))
           ->where("datatopicsid = ?",trim($tid))
           ->where("datausersid= ?",$datausersid);

$stmt = $this->db->query($select);
I circumvented the problem by using: ->where("substr(opinion,1,100) = ?",trim(substr($opinion,1,100)))

This is not a perfect solution, but for my purposes, the select statement using substr() suffices.

Note that I have no problem inserting long strings into the same table/column. The disconnect problem only appears for me on the PDO select with relatively long text strings.

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/12/18 12:47

    >asahina1979 さん
    回答有難う御座います!

    クエリー全体で360文字で、バインドされる文字の長さは最大で20文字でしたので、
    今回は別の原因の様です。

    バインド等が長過ぎた場合も Connection reset by peer となるのですね。
    勉強不足でした。

    キャンセル

  • 2018/12/18 12:59

    この回答者(SO)の人の設定だと1000文字(バイト)ってだけであって
    同じバイト数だから安全とは限らないけどね。

    キャンセル

+1

エラーのハンドリングは全て行えていますか?
9以降でしたが、エラーの状態で、COMMITしてしまうと、DBにプロセスが残るというのを経験したことがあります。

追記

postgres側で、Connection reset by peerということはpostgreas処理中にセッションが切断したって事ですね。
先の回答は逆の話ですから関係なさそうです。

追記

postgresからのメッセージを受けているなら、postgres自身のタイムアウトの可能性が高そうですね。
statement_timeoutを確認してみて下さい

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/12/18 11:09

    横から興味本位で恐縮ですが、それって仕様でした?バグでした?

    キャンセル

  • 2018/12/18 11:13

    早速の回答有難う御座います。
    現状エラーのハンドリングは全ては行えてないです。
    PostgreSQLのログから、クエリー発行でのエラーは発生していませんが、上記エラーメッセージで止まるため、COMMITの処理までは到達していないです。

    キャンセル

  • 2018/12/18 11:17 編集

    >te2ji さん
    エラーハンドリングが不足しているという処理の不備でしたので、調査までは行っていません。

    >dntym さん
    伝えたいのは、エラーを無視して先に進めると別なところでエラーになるという事です。

    キャンセル

  • 2018/12/18 11:21

    興味本位の質問に回答ありがとうございました!

    キャンセル

  • 2018/12/18 11:28

    >sazi さん
    有難う御座います。
    先ずはエラーハンドリング整備をすすめます。

    キャンセル

  • 2018/12/18 11:44

    phpは詳しくないので分かりませんが、php側でセッションが切断されたかどうかはログなど残らないのでしょうか?

    キャンセル

  • 2018/12/18 11:58

    コメント有難う御座います。

    セッション切断によるPHP側での直接なエラー出力は個人的には見たことが無いです(知らないだけかもしれません)
    PHPとの接続がタイムアウトの際にはPHP側はPDOオブジェクトからエラーが受け取れるので手動でエラーログを出しています。
    タイムアウトの場合PostgreSQL側のログは以下のメッセージでした。
    LOG: could not receive data from client: Connection timed out
    LOG: unexpected EOF on client connection

    今回のエラーは初遭遇なのでちょっと難航してます。

    キャンセル

  • 2018/12/18 13:17

    >sazi さん
    続報有難う御座います。statement_timeoutは設定されていない事を確認しました。

    ./postgresql.conf
    #statement_timeout = 0 # in milliseconds, 0 is disabled

    データベース=# show statement_timeout;
    statement_timeout
    -------------------
    0
    (1 row)

    キャンセル

  • 2018/12/18 13:21

    うーん。因みに時間の掛かるクエリーというのはどの程度のものですか?

    キャンセル

  • 2018/12/18 13:51

    >sazi さん
    コメント有難う御座います。
    ①~③はそれぞれ別のサーバーで同じソースコードが動いており、データ件数はバラツキがあります。
    バッチプログラムを再実行すると全く同じ処理を繰り返して実行することが出来ます。
    プロセスが残った場合は一度KILLして再実行すると概ね完走できます(止まる事もあります)


    LOG: statement: delete from テーブル名 where entry_date < '2017-12-03 00:00:00'
    LOG: duration: 171337.362 ms
    LOG: could not receive data from client: Connection reset by peer


    LOG: statement: delete from テーブル名 where entry_date < '2017-12-03 00:00:00'
    LOG: duration: 145444.582 ms
    LOG: could not receive data from client: Connection reset by peer


    LOG: statement: insert into テーブル名 (カラム) サブクエリ
    LOG: duration: 156413.171 ms
    LOG: could not receive data from client: Connection reset by peer

    キャンセル

  • 2018/12/18 14:09

    その時のCPU負荷やI/Oの負荷はどの程度でしょう?
    トランザクションが大きすぎて、サーバーそのものに負荷がかかっているのではないでしょうか

    キャンセル

  • 2018/12/18 14:11

    wal_buffersはどうなっていますか?

    キャンセル

  • 2018/12/18 14:32

    こちらはサンプルが少ないので申し訳ないのですが、

    CPU使用率は 1% 程度で
    I/O負荷は 30% 程度でした。

    wal_buffersは設定されていませんでした。
    ./postgresql.conf
    #wal_buffers = 64kB # min 32kB

    メモリが集計開始直前まで利用率がほぼ 100%、
    スワップ利用率が 1.75% で、集計辺りから70%台に
    下がっているので負荷については危険な香りはしますね。

    キャンセル

  • 2018/12/18 14:50

    処理にかかる時間からみるとトランザクションバッファに収まり切れていないとみるべきでしょう。
    wal_buffersを広げて、後はそれに収まらなければ、トランザクション分割という対処かと思います。

    キャンセル

  • 2018/12/18 15:19

    >sazi さん
    回答有難う御座います。
    wal_buffersの設定変更が難しいため、
    トランザクション分割から進めてみます。

    キャンセル

check解決した方法

0

トランザクションの分割とクエリーの最適化で完走。

クエリに時間がかかってもそのまま実行する様にしたかったのですが、
個別のクエリーを最適化しエラーが出ない範囲内に収める事で収束しました。

$con = new PDO(DSN, USERNAME, PASSWORD);
$con->begin();
$con->exec($delete_sql1, $where); //集計テーブルクリア
$con->exec($delete_sql2, $where); //集計テーブルクリア
$con->exec($delete_sql3, $where); //集計テーブルクリア
//<<---↑このクエリに時間がかかった場合はログがここまでになる

$con->exec($insert_sql1, $where); //集計テーブルへ集計データを挿入
$con->exec($insert_sql2, $where); //集計テーブルへ集計データを挿入
$con->exec($insert_sql3, $where); //集計テーブルへ集計データを挿入
$con->commit();

$con = new PDO(DSN, USERNAME, PASSWORD);
$con->begin();
$con->exec($delete_sql1, $where); //集計テーブルクリア
$con->commit();
$con->begin();
$con->exec($delete_sql2, $where); //集計テーブルクリア
$con->commit();
$con->begin();
$con->exec($delete_sql3, $where); //集計テーブルクリア
$con->commit();

$con->begin();
$con->exec($insert_sql1, $where); //集計テーブルへ集計データを挿入
$con->commit();
$con->begin();
$con->exec($insert_sql2, $where); //集計テーブルへ集計データを挿入
$con->commit();
$con->begin();
$con->exec($insert_sql3, $where); //集計テーブルへ集計データを挿入
$con->commit();

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

同じタグがついた質問を見る

  • PHP

    24011questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

  • PostgreSQL

    1354questions

    PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

  • トップ
  • PHPに関する質問
  • PHPの集計プログラムでPostgreSQLのログにConnection reset by peerと表示されて完走しないままプロセスが残留してしまう