最近、ユーザー データベース名にすでに「max_user_connections」を超えるアクティブな接続があるというエラー メッセージが Web サイトに表示され、Web サイトが麻痺しました。この問題を研究する必要がある。
max_user_connections は、MySQL ユーザー接続数の最大値設定です。ステートメント全体は、サーバー上の MySQL の最大接続数パラメーターの設定が不十分であることを意味します。解決策: MySQL インストール ディレクトリの my.ini または my.cnf ファイルの max_user_connections パラメータの値を変更し、MySQL サーバーを再起動します。
ただし、通常は、MySQL のデフォルトの接続数 100 で十分です。手続き的な観点から考える必要があります。 MySQL のデフォルトの最大接続数は 100 (N) ですが、接続がいっぱいになったときに管理者が追い出されるのを防ぐために、一般ユーザーが実際に使用する接続は 1 つだけです。多くの Web サイトの実行中に接続が制限されるのは、10 回中 9 回、Web サイトへの実際のアクセス数が多すぎて接続数が標準を超えているためではなく、不合理な方法を使用しているためだと思います。ウェブサイトプログラムの設計アーキテクチャまたはデータ構造が原因。制限を超える異常な接続の考えられる理由は次のとおりです (Tianyuan のリアルタイム概要は完全ではない、またはエラーがない可能性があり、参照のみを目的としています):
その他の理由により、データベースのデータ インタラクション時間が長くなったり、インタラクションの数が増加したりすることがあります。したがって、この種の問題が発生した場合は、まずプログラムに接続の解放に失敗するバグがあるかどうかを検討し、次にソフトウェアとハードウェアの最適化を検討する必要があります。もちろん、MySQL の接続数を変更することもソフトウェア最適化の手法の 1 つです。学習する姿勢で自分なりの理由を検討して、この問題を解決できることを願っています。本当に理由が見つからない場合は、最初に接続数を変更し、本当の原因の特定を延期する必要があります。
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 が最大接続数 1000 で構成され、MySQL が最大接続数 100 で構成されているとします。Apache サーバーが 200 の同時アクセスを受信すると、そのうちの 100 はデータベース アクセスを伴い、残りの 100 はデータベース アクセスを伴いません。このため、その時点では使用可能なデータベース接続がなかったため、100 個の同時データベース アクセスによって同時に 100 個の永続的なデータベース接続が生成され、これらの操作が完了しないとデータベース接続の最大数に達します。これらの操作が完了すると、対応する接続がプロセス プールに追加され、そのうち 100 個がデータベース接続を持ちます。 Apache Idle 子プロセスはアクセス要求に対してランダムに選択されるため、取得される子プロセスはデータベース接続を含まない 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 について
しかし、2つの問題があります:
長い接続を使用する場合 (つまり、接続後に閉じない場合)、最後に mysql_close が呼び出される場合、毎回 mysql_free_result を呼び出す必要がありますか?
==9397== 16,468 (88 direct, 16,380 indirect) bytes in 1 blocks are definitely lost in loss record 4 of 5 ==9397== at 0x40219B3: malloc (vg_replace_malloc.c:195) ==9397== by 0x8053EA2: my_malloc (in /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<unsigned int, std::less<unsigned int>, std::allocator<unsigned int> >&) (db_openright.cpp:58) ==9397== by 0x8049F10: main (test.cpp:27)
以后再慢慢研究。。