PHP activerecord mysqlサーバーがなくなりました

私はしばらくの間 php-activerecord を使用していますが、とても気に入っています。 Php-activerecordは ActiveRecordパターンに基づくオープンソースのORMライブラリです。しかし、私は最近レンチに基づいたwebsocketアプリケーションと組み合わせて使用​​することを試みました。

これは完全に機能しますが、ウェブソケットを常に利用できるようにするためには、アプリケーションをLinux上でデーモンとして実行する必要があるスクリプトを開始するためです。アプリケーションを使用しないでしばらくしてからもう一度使用しようとすると、データベース例外が発生します。

最初は警告を出します。

PHP Warning: Error while sending QUERY packet. PID=XXXXX in /home/user/domains/example.com/public_html/vendor/php-activerecord/php-activerecord/lib/Connection.php on line 322

それからそれは致命的なエラーを投げます:

PHP Fatal error: Uncaught exception 'ActiveRecord\DatabaseException' with message 'exception 'PDOException' with message 'SQLSTATE[HY000]: General error: 2006 MySQL server has gone away' in /home/user/domains/example.com/public_html/vendor/php-activerecord/php-activerecord/lib/Connection.php:322

スタックトレース:

#0 /home/user/domains/example.com/public_html/vendor/php-activerecord/php-activerecord/lib/Connection.php(322): PDOStatement->execute(Array)

#1 /home/user/domains/example.com/public_html/vendor/php-activerecord/php-activerecord/lib/Table.php(218): ActiveRecord\Connection->query('SELECT * FROM ...', Array)

#2 /home/user/domains/example.com/public_html/vendor/php-activerecord/php-activerecord/lib/Table.php(209): ActiveRecord\Table->find_by_sql('SELECT * FROM `...', Array, false, NULL)

#3 /home/user/domains/example.com/public_html/vendor/php-activerecord/php-activerecord/lib/Model.php(1567): ActiveRecord\Table->find(Array)

#4 in /home/user/domains/example.com/public_html/vendor/php-activerecord/lib/Connection.php on line 325

php-activerecordがmysql接続をWebSocketサーバが実行されている間ずっと開いたままにしているように見えますが、自動的にクエリを再接続して再度実行しようとしても、これは問題になりません。しかし、そうではありません。

MYSQL_OPT_RECONNECT の設定について何か読んだことがあります。しかし、それがうまくいくかどうか、またはphp-activerecordを使用してそのオプションを設定する方法がわかりません。この分野で経験を積んだ人はいますか。

編集:これが私のグローバルタイムアウト設定変数です。

VARIABLE_NAME                   VARIABLE_VALUE  
DELAYED_INSERT_TIMEOUT          300
WAIT_TIMEOUT                    28800
CONNECT_TIMEOUT                 10
LOCK_WAIT_TIMEOUT               31536000
INNODB_ROLLBACK_ON_TIMEOUT      OFF
THREAD_POOL_IDLE_TIMEOUT        60
NET_WRITE_TIMEOUT               60
INNODB_LOCK_WAIT_TIMEOUT        50
INTERACTIVE_TIMEOUT             28800
DEADLOCK_TIMEOUT_LONG           50000000
SLAVE_NET_TIMEOUT               3600
DEADLOCK_TIMEOUT_SHORT          10000
NET_READ_TIMEOUT                30
12
あなたは、接続を8時間以上続けようとしていますか?
追加された 著者 Rick James,
あなたは、接続を8時間以上続けようとしていますか?
追加された 著者 Rick James,
私は同じ問題を抱えていました。
追加された 著者 Memet Olsen,
私は同じ問題を抱えていました。
追加された 著者 Memet Olsen,
PHPでデータベースの自動再接続を有効にする方法を確認しましたか。。それによれば、PDOで MYSQL_OPT_RECONNECT を設定することはできません(そしてphp-activerecordはPDOを使用します)。おそらく回避策は1時間ごとに単純なクエリを実行することですか?
追加された 著者 VolenD,
PHPでデータベースの自動再接続を有効にする方法を確認しましたか。。それによれば、PDOで MYSQL_OPT_RECONNECT を設定することはできません(そしてphp-activerecordはPDOを使用します)。おそらく回避策は1時間ごとに単純なクエリを実行することですか?
追加された 著者 VolenD,
あなたはPHPでソケットサービスを実装しましたか? DBとのつながりを保持するためのコードを教えてください。 tcpではなく .sock でDBに接続してみましたか?
追加された 著者 yergo,
あなたはPHPでソケットサービスを実装しましたか? DBとのつながりを保持するためのコードを教えてください。 tcpではなく .sock でDBに接続してみましたか?
追加された 著者 yergo,
IMO、 MYSQL_OPT_RECONNECT は良い解決策ではありません。私の答えを以下に読んでください。実際の実装に基づいています。
追加された 著者 ihsan,
IMO、 MYSQL_OPT_RECONNECT は良い解決策ではありません。私の答えを以下に読んでください。実際の実装に基づいています。
追加された 著者 ihsan,
Active Recordを使って、あなたはあなたが値するものを手に入れました。パターンとしてのActive Recordは、あらゆるDB開発者にとって嫌悪であり、そのパターンに基づいたライブラリでもあります。使用するように設計されているようにRDBMSを使用する方法を学ぶか、必要なのがクラスのパッシブデータストアだけであれば非リレーショナルデータストアを使用する方法を学んでください。
追加された 著者 David Soussan,
Active Recordを使って、あなたはあなたが値するものを手に入れました。パターンとしてのActive Recordは、あらゆるDB開発者にとって嫌悪であり、そのパターンに基づいたライブラリでもあります。使用するように設計されているようにRDBMSを使用する方法を学ぶか、必要なのがクラスのパッシブデータストアだけであれば非リレーショナルデータストアを使用する方法を学んでください。
追加された 著者 David Soussan,
@Dimitriはい、私はフルコントロールを持っています、そして私は私の質問を編集しました。
追加された 著者 RTB,
@Dimitriはい、私はフルコントロールを持っています、そして私は私の質問を編集しました。
追加された 著者 RTB,
データベース設定を完全に制御できますか?あなたはあなたの設定で設定したすべてのタイムアウトをリストすることができますか?設定が空の場合は、mysqlからグローバル変数を選択して、 'timeout'を含むすべての行をポストします。
追加された 著者 Dimitri,
データベース設定を完全に制御できますか?あなたはあなたの設定で設定したすべてのタイムアウトをリストすることができますか?設定が空の場合は、mysqlからグローバル変数を選択して、 'timeout'を含むすべての行をポストします。
追加された 著者 Dimitri,

12 答え

PHP ActiveRecordはPDOを使用します。 PDO接続を閉じる方法は絶対にありません。長時間実行されているバックグラウンドタスクでは、これは間違ったDB層です。

次のスニペットを使ってPDO接続の切断に影響を与えることができます。

//if not using ZF2 libraries, disconnect in some other way
$db->getDriver()->getConnection()->disconnect()
$db = NULL;
gc_collect_cycles();

切断し、参照をnullに設定してからガベージコレクタを実行します。希望はそれが実際に接続を閉じるためにPDOの内部__destructメソッドを呼び出すことです。

You must manage your DB connections in your own long running script. You must disconnect if your worker hasn't had to process work in a while, and you must reconnect when you have work.

本当の解決策は、PDOを使用せずに通常通りに切断して再接続することです。

単純にサーバーとクライアントの両方のライブラリタイムアウトを無限に設定すると、決して制御不能なスクリプトが発生してサーバー全体を再起動しなければならないという問題に遭遇するでしょう(タイムアウトを台無しにするのはお勧めできません)。

編集:私は実際にこの正確な問題を抱えており、昨年の仕事でこの正確な解決策を使用しました。これは私の問題の99%を解決しました。それでも、たまにはキャッチすることができず、再接続しようとすることができなかった漂遊接続例外がありました。私はそれらの漂遊の接続エラーを取り除くために一日一回プロセスを再開するだけです。だからこそ、私の答えは、PDOを使わないでください。今すぐ切り替えて、切断と再接続を実際に制御できます。

5
追加された
... mysqliそれで?
追加された 著者 angelcool.net,

PHP ActiveRecordはPDOを使用します。 PDO接続を閉じる方法は絶対にありません。長時間実行されているバックグラウンドタスクでは、これは間違ったDB層です。

次のスニペットを使ってPDO接続の切断に影響を与えることができます。

//if not using ZF2 libraries, disconnect in some other way
$db->getDriver()->getConnection()->disconnect()
$db = NULL;
gc_collect_cycles();

切断し、参照をnullに設定してからガベージコレクタを実行します。希望はそれが実際に接続を閉じるためにPDOの内部__destructメソッドを呼び出すことです。

You must manage your DB connections in your own long running script. You must disconnect if your worker hasn't had to process work in a while, and you must reconnect when you have work.

本当の解決策は、PDOを使用せずに通常通りに切断して再接続することです。

単純にサーバーとクライアントの両方のライブラリタイムアウトを無限に設定すると、決して制御不能なスクリプトが発生してサーバー全体を再起動しなければならないという問題に遭遇するでしょう(タイムアウトを台無しにするのはお勧めできません)。

編集:私は実際にこの正確な問題を抱えており、昨年の仕事でこの正確な解決策を使用しました。これは私の問題の99%を解決しました。それでも、たまにはキャッチすることができず、再接続しようとすることができなかった漂遊接続例外がありました。私はそれらの漂遊の接続エラーを取り除くために一日一回プロセスを再開するだけです。だからこそ、私の答えは、PDOを使わないでください。今すぐ切り替えて、切断と再接続を実際に制御できます。

5
追加された
... mysqliそれで?
追加された 著者 angelcool.net,

前述のように、PHPスクリプトでのMySQLはしばらくの間、両者の間に通信がないとタイムアウトします。 アイドル状態の接続はサーバーのリソースを浪費するので、これは良いことです。

「サーバーがなくなった」というエラーは、2つのクエリ間で比較的長い計算が行われるときに発生します。

それを防ぐために、

  • Periodically execute a SELECT 1 query during your execution
  • Create a wrapper around your queries which checks if connection is valid before executing
  • Use answer from this post

しかし、MySQLを再設定して接続を開いたままにしておくと、不注意なプログラミングが促進され、それに対してアドバイスが得られると私は考えています。

1
追加された

前述のように、PHPスクリプトでのMySQLはしばらくの間、両者の間に通信がないとタイムアウトします。 アイドル状態の接続はサーバーのリソースを浪費するので、これは良いことです。

「サーバーがなくなった」というエラーは、2つのクエリ間で比較的長い計算が行われるときに発生します。

それを防ぐために、

  • Periodically execute a SELECT 1 query during your execution
  • Create a wrapper around your queries which checks if connection is valid before executing
  • Use answer from this post

しかし、MySQLを再設定して接続を開いたままにしておくと、不注意なプログラミングが促進され、それに対してアドバイスが得られると私は考えています。

1
追加された

MySQLサーバーがエラーをなくした最も一般的な理由は、サーバーがタイムアウトして接続を閉じたことです。

次のように変更してみてください。

max_allowed_packet=64M

あなたがたくさんのリクエストを持っているならこれを設定し、それをあなたの環境に関連しているのでもっと大きく設定しないでください。

max_connections=1000

この行を my.cnf ファイルに追加すると問題が解決する可能性があります。変更が完了したら、MySQLサービスを再起動します。

Read more on MySQL server has gone away

うまくいかない場合はこちらをお試しください自動再接続機能もあります。

1
追加された
自動的に再接続すると、状態情報が失われるため、問題が発生する可能性があります。特に、あなたがトランザクションを利用している場合、それは切断によってロールバックされます。再接続後も続行すると、データが失われたり変更されたりする可能性があります。
追加された 著者 Rick James,

MySQLサーバーがエラーをなくした最も一般的な理由は、サーバーがタイムアウトして接続を閉じたことです。

次のように変更してみてください。

max_allowed_packet=64M

あなたがたくさんのリクエストを持っているならこれを設定し、それをあなたの環境に関連しているのでもっと大きく設定しないでください。

max_connections=1000

この行を my.cnf ファイルに追加すると問題が解決する可能性があります。変更が完了したら、MySQLサービスを再起動します。

Read more on MySQL server has gone away

うまくいかない場合はこちらをお試しください自動再接続機能もあります。

1
追加された
自動的に再接続すると、状態情報が失われるため、問題が発生する可能性があります。特に、あなたがトランザクションを利用している場合、それは切断によってロールバックされます。再接続後も続行すると、データが失われたり変更されたりする可能性があります。
追加された 著者 Rick James,

DBが複数の同時接続とクエリを処理していない場合は、「無限」のタイムアウトを設定できます。これはDBリソースに大きな影響を与えません。最善の方法は、タイムアウトを更新して接続を維持するためにpingパケットを送信することです(SELECT 1)。

1
追加された

DBが複数の同時接続とクエリを処理していない場合は、「無限」のタイムアウトを設定できます。これはDBリソースに大きな影響を与えません。最善の方法は、タイムアウトを更新して接続を維持するためにpingパケットを送信することです(SELECT 1)。

1
追加された

場合によってはORMがクエリを組み合わせてパフォーマンスを向上させるため、クエリのサイズにすることもできます。

max_allowed_pa​​cket = 128Mを設定してみてください。少なくとも診断としては役に立つはずです。

1
追加された

場合によってはORMがクエリを組み合わせてパフォーマンスを向上させるため、クエリのサイズにすることもできます。

max_allowed_pa​​cket = 128Mを設定してみてください。少なくとも診断としては役に立つはずです。

1
追加された

そのような問題を解決するために、私はあなたに提案します:

  1. Gearman Job Serverを使用してプロセスを配布する( http://gearman.org/
  2. Supervisorを使用してこれらのプロセスを簡単に管理する( http://supervisord.org/

これはどうですか。

Webソケットアプリケーションをデーモンとして実行します。これは、すでに行ったのと同じです(おそらくcronを使用して)。さらに良いことには、Supervisorを使って管理します。 Supervisorの起動時にSupervisorが起動し、デーモンが停止した場合は自動再起動するように設定します。

設定例:

[program:my-daemon]
command=/usr/bin/php /path/to/your/daemon/script
autostart=true
autorestart=true

次に、アプリケーションデーモン内でクエリ処理を実行するのではなく、それを処理するGearmanワーカーを作成します。登録されると、ワーカーは実行されたり呼び出されたりするのを待ちます。必要に応じて、必要なワークロードパラメータとともに、WebSocketアプリケーションからWorkerを呼び出す必要があります(このワークロードの用語の説明については、GearmanのWebサイトを参照してください)。

Workerで、デーモンによって要求されたジョブがすでに終了したときに停止/終了するように設定します。これで、接続がすぐに閉じられるので、「mysqlサーバーは問題を解決しました」ということにはなりません。

最後に、デーモンと同じようにWorkerを常に利用可能にする必要があります。そのため、デーモンと同様に、次のように、Workerが停止または停止したときにSupervisorを自動起動および自動再起動するように設定します。

[program:my-worker]
command=/usr/bin/php /path/to/your/worker/script
autostart=true
autorestart=true

もう一つ興味深いことは、あなたが生きているのを待ちたいあなたが好きなだけ多くのワーカーを追加できるということです。以下の設定を追加するだけです。

numprocs=9 #change it to any number
process_name=%(program_name)s_%(process_num)02d #to identity worker number

各プロセスを自動再起動するようにSupervisorに指示したので、バックグラウンドで常時稼働しているワーカーがいます。

Here is another explanation about this strategy: http://www.masnun.com/2011/11/02/gearman-php-and-supervisor-processing-background-jobs-with-sanity.html

それが役立つことを願っています!

0
追加された
意気消沈した人は、戦略をよく読んでください。私も投稿したリンクを読んでください! 「mysqlサーバーがなくなった」という問題は解決するのが簡単なようですが、そうではありません。
追加された 著者 ihsan,
@ArunPoudelはなぜですか?実稼働環境でそれらを実装しました。 mysqlサーバーがなくなったのは、接続が開かれている時間が長すぎるためで、PHPは長期の実行には適していません。
追加された 著者 ihsan,
@ArunPoudelなぜ関係ないのですか? 「mysqlサーバーがなくなった」という問題を解決します。
追加された 著者 ihsan,
@ArunPoudelだから今、あなたはそれが関連していると言っているが、慣用句ですか?他に解決策がある場合は、あなた自身の答えを書いてください。それがSOの好ましい方法です。 *実際に私はあなたが慣用句で何を意味するのか理解していません。
追加された 著者 ihsan,
はい、私はしました、そして、それは決してポストに関連していません。 OPが持っている問題はあなたが解決しようとしているものとはかなり異なります。
追加された 著者 Arun Poudel,
これがOPの問題を解決するとは思わない。
追加された 著者 Arun Poudel,
はい、非常識なアプローチを使用しています。問題を解決するだけではありません。しかし、慣用的な方法でそれをやっています。この種の問題を処理する方法は他にもありますが、そのうちの1つが再接続フラグです。
追加された 著者 Arun Poudel,

そのような問題を解決するために、私はあなたに提案します:

  1. Gearman Job Serverを使用してプロセスを配布する( http://gearman.org/
  2. Supervisorを使用してこれらのプロセスを簡単に管理する( http://supervisord.org/

これはどうですか。

Webソケットアプリケーションをデーモンとして実行します。これは、すでに行ったのと同じです(おそらくcronを使用して)。さらに良いことには、Supervisorを使って管理します。 Supervisorの起動時にSupervisorが起動し、デーモンが停止した場合は自動再起動するように設定します。

設定例:

[program:my-daemon]
command=/usr/bin/php /path/to/your/daemon/script
autostart=true
autorestart=true

次に、アプリケーションデーモン内でクエリ処理を実行するのではなく、それを処理するGearmanワーカーを作成します。登録されると、ワーカーは実行されたり呼び出されたりするのを待ちます。必要に応じて、必要なワークロードパラメータとともに、WebSocketアプリケーションからWorkerを呼び出す必要があります(このワークロードの用語の説明については、GearmanのWebサイトを参照してください)。

Workerで、デーモンによって要求されたジョブがすでに終了したときに停止/終了するように設定します。これで、接続がすぐに閉じられるので、「mysqlサーバーは問題を解決しました」ということにはなりません。

最後に、デーモンと同じようにWorkerを常に利用可能にする必要があります。そのため、デーモンと同様に、次のように、Workerが停止または停止したときにSupervisorを自動起動および自動再起動するように設定します。

[program:my-worker]
command=/usr/bin/php /path/to/your/worker/script
autostart=true
autorestart=true

もう一つ興味深いことは、あなたが生きているのを待ちたいあなたが好きなだけ多くのワーカーを追加できるということです。以下の設定を追加するだけです。

numprocs=9 #change it to any number
process_name=%(program_name)s_%(process_num)02d #to identity worker number

各プロセスを自動再起動するようにSupervisorに指示したので、バックグラウンドで常時稼働しているワーカーがいます。

Here is another explanation about this strategy: http://www.masnun.com/2011/11/02/gearman-php-and-supervisor-processing-background-jobs-with-sanity.html

それが役立つことを願っています!

0
追加された
意気消沈した人は、戦略をよく読んでください。私も投稿したリンクを読んでください! 「mysqlサーバーがなくなった」という問題は解決するのが簡単なようですが、そうではありません。
追加された 著者 ihsan,
@ArunPoudelはなぜですか?実稼働環境でそれらを実装しました。 mysqlサーバーがなくなったのは、接続が開かれている時間が長すぎるためで、PHPは長期の実行には適していません。
追加された 著者 ihsan,
@ArunPoudelなぜ関係ないのですか? 「mysqlサーバーがなくなった」という問題を解決します。
追加された 著者 ihsan,
@ArunPoudelだから今、あなたはそれが関連していると言っているが、慣用句ですか?他に解決策がある場合は、あなた自身の答えを書いてください。それがSOの好ましい方法です。 *実際に私はあなたが慣用句で何を意味するのか理解していません。
追加された 著者 ihsan,
はい、私はしました、そして、それは決してポストに関連していません。 OPが持っている問題はあなたが解決しようとしているものとはかなり異なります。
追加された 著者 Arun Poudel,
これがOPの問題を解決するとは思わない。
追加された 著者 Arun Poudel,
はい、非常識なアプローチを使用しています。問題を解決するだけではありません。しかし、慣用的な方法でそれをやっています。この種の問題を処理する方法は他にもありますが、そのうちの1つが再接続フラグです。
追加された 著者 Arun Poudel,
PHP - 日本のコミュニティ [ja]
PHP - 日本のコミュニティ [ja]
4 参加者の

このグループではPHPについて話します。 パートナー:kotaeta.com