7

私のプロジェクトでは、オープン ソースの PHP MySQL ライブラリhttps://github.com/ajillion/PHP-MySQLi-Database-Classを使用しています。

しかし、プロジェクトの中間レポート: 「致命的なエラー: 422 行目の /home1/flipalbu/public_html/kvisofttest/login-admin/Lib/class.MysqliDb.php で、134217728 バイトの許容メモリ サイズが使い果たされました (4294967296 バイトを割り当てようとしました)。 " このエラー ,

私のサーバーは: linux x86_64

PHP バージョン 5.4.17

Mysql バージョン: 5.5.32

メモリ制限 = 128M

422 行目:call_user_func_array (array ($ stmt, 'bind_result'), $ parameters);

コードのクエリ部分:

    $ db = new MysqliDb ('LocalHost', 'root', 'PASSWD', 'DB');
$ wqdb = $ db-> query ("SELECT * FROM db_table");
foreach ($ wqdb as $ row) {
     $ con. = $ row ['ID'];
}
echo $ con;

それを解決する方法はありますか?


/** エラーコード **/

 protected function _dynamicBindResults(mysqli_stmt $stmt)
        {
            $parameters = array();
            $results = array();

            $meta = $stmt->result_metadata();

            $row = array();
            while ($field = $meta->fetch_field()) {
                $row[$field->name] = null;
                $parameters[] = & $row[$field->name];
            }

            call_user_func_array(array($stmt, 'bind_result'), $parameters);

            while ($stmt->fetch()) {
                $x = array();
                foreach ($row as $key => $val) {
                    $x[$key] = $val;
                }
                array_push($results, $x);
            }
            return $results;
        }
4

4 に答える 4

24

ここでこのバグレポートを読みました: https://bugs.php.net/bug.php?id=51386

テーブルの列にlongblobまたはがあるため、問題が発生したようです。longtext

longtext/longblob最大長が4294967295[4GB] であるため、mysqli はバッファにそのメモリを割り当てて、何も失われないようにします。(16777215 [16MB] 最大長)を使用することをお勧めしますmediumtext。通常はこれで十分です。

更新: この回答にはいくつかのアクティビティが見られたため、Phil_1984 からこのソリューションを追加しました(コメントを参照)

私は mysqli を使用し、php dev からの引用を読んだ後、$stmt->store_result(); を追加します。execute と bind_result の間で問題が解決するようです

=> $stmt->store_result()mysqli を使用すると、longblob/を使用しlongtextてエラーを発生させずに使用できます。

-

古い回答: 列を別のタイプ (mediumtext) に変更するか、PDO を使用することをお勧めします (その問題はないと思います)。ただし、列をロングテキストのままにしたい場合は、mysql ライブラリを切り替える必要があります

PHP Dev からの引用:

これは、libmysql (常に 5.2 以前) を使用し、libmysql が 5.3 で有効になっている場合の ext/mysqli の既知の制限です。その理由は、サーバーが列に関するあまり具体的なメタデータを送信しないためです。この longtext の最大長は 4G で、ext/mysqli は最大長でバインドを試行し、データの損失が発生しないようにします (データは C レベルのバインド バッファーに収まりません)。ただし、これは longtext/longblob 列の場合は 4G を意味します。ext/mysqli は、それを回避する方法を持つように変更されました。データをローカルに保存する mysqli_stmt_store_result() を呼び出す必要があります。これはもちろん、PHP のメモリ使用量が高くなることを意味します。ただし、libmysql を使用しているため、PHP のメモリ制限に達することはありません。store_result の間、すべての列の max_length が計算され、次に bind_result が実行されると、max_length のサイズのバッファーのみが割り当てられます。これは 4G よりも確実に低くなります。つまり、 store_result bind_result fetch...fetch...fetch を実行する準備をします

于 2013-08-08T08:58:29.167 に答える
4

テーブル全体を一度に読み込もうとしていて、そのテーブルに多数の行と列がある場合、メモリ不足は避けられません。php.ini でメモリ制限を引き上げることで延期できますが、数千行を追加した場合にのみ問題が再発します。

スクリプトが何を取得するかについてより賢明になるように、スクリプトを書き直す必要があります。特定のレコードのみが必要な場合、テーブル全体をプルダウンして、結果セットで必要な行を探すのは非常に非効率的です。WHERE 句を使用して、本当に取得したいものを指定します。PHP/SQL アプリケーションの経験則は、「必要なものを指定するために可能な限り SQL を使用し、それを使用して必要なことを PHP で実行する」です。

もちろん、PHP でテーブル全体を処理する必要があるのには、まったく正当な理由があるかもしれません。その場合、LIMIT と OFFSET を使用してチャンク (一度に 100 行など) でデータをフェッチし、それらの行を処理し、次のチャンクを取得し、テーブル全体を処理するまでそれらを処理する必要があります。テーブル全体を一度にロードしようとするよりもメモリがはるかに少なくなります。

于 2013-08-08T08:52:43.930 に答える
1

巨大なテーブルとは思えません!無限ループみたい!約4GBを割り当てようとしますが、そんなに大きなテーブルがあるとは思いません....

ここでループを作成していないことを確認してください。

call_user_func_array (array ($ stmt, 'bind_result'), $ parameters);

おそらく、この行の周りにあるコードを投稿する必要があります。

于 2013-08-08T08:56:23.053 に答える
0

使用可能な最大メモリを超えています。次の 2 つのオプションがあります。

  • memory_limit構成 (のディレクティブphp.ini) によって、または実行時に、各 PHP スクリプトに許可される最大メモリを増やします。ini_set('memory_limit', '200M')

  • 必要な情報のみを処理するようにコードを改善します。

于 2013-08-08T08:58:19.467 に答える