現在の位置: ホーム> 最新記事一覧> next_result()を使用した後に結果セットを解放しないことによって引き起こされるメモリ漏れの問題

next_result()を使用した後に結果セットを解放しないことによって引き起こされるメモリ漏れの問題

gitbox 2025-04-29

PHPを使用してMySQLデータベースを操作する場合、 MySQLI拡張機能をマルチクエリに使用する場合、 next_result()メソッドに遭遇する可能性があります。そして、多くの人々は重要な詳細を無視しています - 。

この記事では、原因、症状、この問題を回避する方法を示します。

背景: next_result()とは

mysqli :: multi_query()を介して複数のSQLSを実行すると、MySQLは複数の結果セットを返します。これらの結果セットは、mysqli :: next_result()から1つずつアクセスでき、各結果のコンテンツはmysqli :: store_result()と併せて取得できます。

サンプルコード:

 $mysqli = new mysqli("localhost", "user", "password", "database");

$sql = "SELECT * FROM users; SELECT * FROM orders;";
if ($mysqli->multi_query($sql)) {
    do {
        if ($result = $mysqli->store_result()) {
            while ($row = $result->fetch_assoc()) {
                // データの各行を処理します
                echo $row["id"] . "<br>";
            }
            // 結果セットをリリースします
            $result->free();
        }
    } while ($mysqli->next_result());
}

この例では、毎回store_result()を介して結果を取得し、使用後に$ result-> free()でリリースします。

問題:結果セットのリリースはありません

$ result-> free()を省略した場合、次のように:

 // ? 未結果セットをリリースします的代码示例
if ($result = $mysqli->store_result()) {
    while ($row = $result->fetch_assoc()) {
        echo $row["id"] . "<br>";
    }
    // 無視した $result->free();
}

その後、プログラムのメモリ使用量は増加し続けます。特に、大量のデータや同時リクエストを大量に処理すると、このメモリリークは非常に明白になります。 MySQLI拡張機能は、結果をクライアントメモリに設定したため、PHPが明示的にリリースすることによってのみこれらのリソースをリサイクルできます。

メモリリークの結果

  • プログラムが長い間実行された後のメモリは急増します。

  • サーバーの応答が遅くなるか、クラッシュします。

  • PHPは、許可されたメモリサイズの使い果たされたエラーを報告します。

  • 追跡されていないパフォーマンスの問題。

これは、交通量の多いAPI、タイミングタスク、またはデーモンで特に致命的です。

それを行う正しい方法

結果セットを処理した後、必ず$ result-> free()を呼び出すことを忘れないでください。さらに、新しい結果セットがあるかどうかを確認し、各呼び出しの後にそれらを処理しますnext_result()

完全な漏れ防止テンプレート:

 $mysqli = new mysqli("localhost", "user", "password", "database");

$sql = "CALL complex_procedure(); CALL another_procedure();";
if ($mysqli->multi_query($sql)) {
    do {
        if ($result = $mysqli->store_result()) {
            while ($row = $result->fetch_assoc()) {
                // 各行を処理します
            }
            $result->free(); // ? 正しくリリースします
        }
    } while ($mysqli->more_results() && $mysqli->next_result());
}

漏れを検出する方法

  • Memory_get_usage()またはXDebugツールを使用して、メモリの使用量を監視します。

  • TOPHTOPなどのLinuxコマンドを使用して、プロセスメモリを監視します。

  • 各クエリの後にメモリ使用量を記録します。

まとめ

mysqli :: next_result()を使用するときに結果セットをリリースしないと、PHPスクリプトのメモリリークが発生します。正しい方法は、結果セットが処理されるたびに$ result-> free()を呼び出すことです。これにより、プログラムの堅牢性を維持するだけでなく、メモリの過剰な使用によって引き起こされるパフォーマンスの問題も回避されます。

これは、バッチ内のデータを処理する複雑なデータインターフェイスまたはサービスを構築する場合に特に重要です。

mysqliマルチリンドルセット処理に関する公式ドキュメントの詳細については、以下にアクセスできます。
https://gitbox.net/docs/php/mysqli-multi-query (想定リンク)

この記事が、PHP開発における一般的な落とし穴を回避するのに役立つことを願っています。