ホームページ  >  記事  >  バックエンド開発  >  900 万台の自転車 MySQL 接続数が制限を超える問題の解決策

900 万台の自転車 MySQL 接続数が制限を超える問題の解決策

WBOY
WBOYオリジナル
2016-07-29 08:46:05898ブラウズ

max_user_connections は、MySQL ユーザー接続数の最大設定です。ステートメント全体は、サーバーの MySQL の最大接続数パラメータが十分に設定されていないことを意味します。解決策: MySQL インストール ディレクトリの my.ini または my.cnf ファイルの max_user_connections パラメータの値を変更し、MySQL サーバーを再起動します。
ただし、通常は、MySQL のデフォルトの接続数 100 で十分です。手続き的な観点から考える必要があります。 MySQL のデフォルトの最大接続数は 100 (N) ですが、接続がいっぱいになったときに管理者が追い出されるのを防ぐために、一般ユーザーが実際に使用する接続は 1 つだけです。多くの Web サイトの実行中に接続が制限されるのは、10 回中 9 回、Web サイトへの実際のアクセス数が多すぎて接続数が標準を超えているためではなく、不合理な方法を使用しているためだと思います。 Web サイトのプログラムのデザイン アーキテクチャまたはデータ構造が原因。制限を超える異常な接続が発生する原因は次のとおりです (Tianyuan のリアルタイム サマリーは完全ではない、またはエラーがない可能性があります。参照のみを目的としています):
人数、オンライン時間、オンライン時間などの統計関数が使用されている場合に発生しやすくなりますビューの数は、メイン プログラム データベースと同じデータ スペースに属します。
特にユーザーが閲覧するたびに複数のデータベースまたはテーブル操作が関与する場合、複雑な動的ページも表示されやすくなります。
また、プログラム設計に無理があったり(例えば、データベースとのやり取りの途中に複雑な処理や待機などの処理が入っているなど)、プログラムにリリースバグがある場合もあります。
コンピューターのハードウェア構成が低すぎますが、インストールされている MySQL のバージョンと構成が高すぎます。
キャッシュ技術は使用されていません。
データベースが最適化されていないか、テーブルの設計が非常に複雑です。
その他の理由により、データベースのデータ インタラクション時間が長くなったり、インタラクションの数が増加したりすることがあります。したがって、この種の問題が発生した場合は、まずプログラムに接続の解放に失敗するバグがあるかどうかを検討し、次にソフトウェアとハ​​ードウェアの最適化を検討する必要があります。もちろん、MySQL の接続数を変更することもソフトウェア最適化の手法の 1 つです。学習する姿勢で自分なりの理由を検討して、この問題を解決できることを願っています。本当に理由が見つからない場合は、まず接続数を変更し、本当の原因の特定を先延ばしにする必要があります。
PHP のデータベース永続接続 mysql_pconnect について
PHP プログラマーは、mysql_pconnect (永続接続) 関数を使用して MySQL データベースに接続できることを知っているはずですが、データベースの永続接続を使用すると効率が向上しますが、実際のアプリケーションでは、データベースの永続接続によって問題が発生することがよくあります。最も一般的な症状は、アクセス数が多い Web サイトで断続的にデータベースに接続できないことが頻繁に発生し、サーバーを再起動した後に「... の接続が多すぎます」のようなエラー メッセージが表示されることです。 、再び正常になりますが、しばらくすると同じ問題が発生します。残念ながら、誰もがこれらの問題の原因を明確に説明できるわけではありませんが、PHP ドキュメントにはいくつかの関連情報が記載されていますが、ここでは恥ずかしがらずに簡単な説明と見解を述べようとしています。すべてが正しいかもしれません。皆さんのフィードバックを歓迎します。
まず、永続的なデータベース接続の定義を見てみましょう。永続的なデータベース接続とは、スクリプトの実行終了時に閉じられない接続を指します。常設接続の要求を受信したとき。 PHP は、(以前に開かれた) 同一の永続接続が既に存在するかどうかを確認します。存在する場合は接続が直接使用され、存在しない場合は新しい接続が確立されます。いわゆる「同じ」接続とは、同じユーザー名とパスワードを使用した同じホストへの接続を指します。
PHP が永続接続を使用して MySQL を操作するには前提条件があります。PHP は、マルチスレッドまたはマルチプロセス Web サーバーのプラグインまたはモジュールとしてインストールする必要があります。最も一般的な形式は、PHP をマルチプロセス Apache サーバーのモジュールとして使用することです。マルチプロセス サーバーの典型的な特徴は、親プロセスと子プロセスのグループが連携して実行され、その中で実際に Web ページを生成するのは子プロセスであることです。クライアントが親プロセスにリクエストを行うと、そのリクエストは他のクライアント リクエストによって占有されていない子プロセスに渡されます。これは、同じクライアントがサーバーに 2 度目にリクエストを行うと、そのリクエストが別の子プロセスによって処理される可能性があることを意味します。永続的な接続を開いた後は、さまざまなサブプロセスから SQL サービスを要求する後続のすべてのページで、確立された SQL サーバー接続を再利用できます。これにより、各子プロセスは、ページが処理されるたびに SQL サーバーへの接続要求を行うのではなく、ライフサイクル中に接続操作を 1 つだけ実行できるようになります。各子プロセスは、サーバーへの独自の独立した永続的な接続を確立します。 PHP 自体にはデータベース接続プールの概念がありませんが、Apache にはプロセス プールの概念があり、Apache の子プロセスが終了すると、mysql_pconnect で開かれた mysql 接続リソースも許可されます。解放されないように、対応する Apache 子プロセスにアタッチされ、プロセス プールに保存されます。その後、次の接続リクエストで再利用できます。すべてが正常であるように見えますが、Apache に大量の同時アクセスがある場合、mysql_pconnect を使用すると、前の Apache 子プロセスによって占有されていた MySQL 接続が閉じられず、MySQL はすぐに最大接続数に達し、後続の接続が確立されません。要求は不可能です。
上記のテキストの一部は PHP ドキュメントからの抜粋です。少し不格好で理解しにくいように思えるかもしれないので、別の例を使用して問題を分かりやすく説明します。
Apache が最大接続数で構成されていると仮定します。 Apache サーバーが 200 の同時アクセスを受信すると、そのうちの 100 はデータベース アクセスに関係し、残りの 100 はデータベース アクセスに関係しません。現時点ではデータベース接続が 100 であるため、同時データベース アクセスは 100 個のデータベース永続接続を同時に生成し、データベース接続の最大数に達すると、これらの操作が完了しないと、他の接続は取得できなくなります。これらの操作が完了すると、Apache のプロセス プールには 200 個のアイドル状態の子プロセスが存在し、そのうちの 100 個がランダムにデータベース接続されます。アクセス要求に対してアイドル状態の子プロセスを選択すると、「子プロセスはおそらくデータベース接続を含まない 100 個のプロセスのうちの 1 つであり、データベース接続が最大値に達しており、残念ながら新しいデータベース接続を正常に確立できません。」というメッセージが表示されます。ページを更新し続けるため、運が良ければ、たまたまデータベース接続を持つ子プロセスが割り当てられ、ページを通常どおり参照できるようになります。アクセス数が多い Web サイトの場合、常に大量の同時実行が行われる可能性があるため、訪問者は常にデータベースに接続できないことに気づく可能性があります。
おそらく、Apache と MySQL の最大接続数を同じサイズに調整することはできないのではないか、と思われるかもしれません。はい、最大接続数を適切に調整することでこの問題はある程度回避できますが、Apache と MySQL の負荷能力は異なります。Apache の負荷容量に応じて設定すると、MySQL の場合は最大接続数が異なります。これが大きすぎる場合、負荷に応じて設定すると、平時で数百万の軍隊をサポートするようなものになります。 MySQL の容量、Apache の場合、この最大接続数は少なすぎるため、過剰に感じられ、Apache の効率を最大限に引き出すことができません。
PHP マニュアルの紹介によれば、データベース常設接続は同時アクセス数が少ない Web サイトにのみ適しているとのことですが、同時アクセス数が少ない Web サイトの場合、データベース常設接続による効率の向上は期待できないようです。つまり、この観点から見ると、PHP のデータベース永続接続は基本的に役に立たない役割であると考えられます。データベース接続プールの概念を使用する必要がある場合は、Apache 自体が提供する sqlrelay または mod_dbd を試すことができます。 。
mysql_free_result と mysql_close について
mysql を使用するときは、mysql_store_result を呼び出してデータを取得した後、それを直接呼び出します:

コードをコピーします コードは次のとおりです:


mysql_free_result(m_res) ult);
mysql_close( m_Database);


しかし、2 つの質問があります:
長い接続を使用する場合 (つまり、接続後に閉じない場合)、最後に mysql_close が呼び出される場合、mysql_free_result を毎回呼び出す必要がありますか?
mysql_close が呼び出された後、データはまだ利用可能ですか?
結論から先にお話しますと、
毎回電話する必要があります。テスト後、mysql_store_result のポインタが毎回異なるため、同じ buf が共有されていないことがわかります。
まだまだ使えます。 valgrind スキャン後、mysql_close を呼び出しただけのスキャン結果は次のとおりです:

コードをコピー コードは次のとおりです:


==9397== 1 ブロック内の 16,468 (直接 88、間接 16,380) バイトが確実に失われます。損失レコード 4/5 で
==9397== 0x40219B3 で: malloc (vg_replace_malloc.c:195)
==9397== 0x8053EA2 で: my_malloc (/data/home/dantezhu/appbase/application/platform/openqqcom/ 内) share/db_openright/ test/test)
==9397== by 0x806D314: mysql_store_result (in /data/home/dantezhu/appbase/application/platform/openqqcom/share/db_openright/test/test)
==9397== by 0x804BB04: CMySQLCppClient: :Result(st_mysql_res*&) (mysql_cpp_client.cpp:127)
==9397== by 0x804AB58: CDBOpenRight::GetUinsByApp(unsigned int, std::set >&) (db_openright.cpp:58)
==9397== by 0x8049F10: main (test.cpp:27)


今後ゆっくり勉強していきます。 。

以上、Nine Million Bicycles の MySQL 接続数が制限を超える問題の解決方法を、Nine Million Bicycles の内容も含めて紹介しました。PHP チュートリアルに興味のある友人の参考になれば幸いです。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。