12

私はPHP を使用して、 AUTOCOMIT を無効にすることで行っていbulk insertsました。RealTime Index

// sphinx connection
$sphinxql = mysqli_connect($sphinxql_host.':'.$sphinxql_port,'',''); 

//do some other time consuming work

//sphinx start transaction
mysqli_begin_transaction($sphinxql);

//do 50k updates or inserts

// Commit transaction
mysqli_commit($sphinxql);

スクリプトを一晩実行し続けました。朝に見ました

PHP Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate
212334 bytes) in

そのため、ファイルを綿密にチェックしたところnohup.out、これらの行に気付きました。

PHP Warning: mysqli_query(): MySQL server has gone away in /home/script.php on line 502
Warning: mysqli_query(): MySQL server has gone away in /home/script.php on line 502

これらの行の前のメモリ使用量は正常でしたが、これらの行の後のメモリ使用量が増加し始め、ヒットし、php mem_limitPHP を与えFatal errorて死亡しました。

in script.php , line 502 is

mysqli_query($sphinxql,$update_query_sphinx);

私の推測では、スフィンクス サーバーは、数時間/分の非アクティブ状態の後に閉じられた/停止しました。

私はsphinx.confで設定しようとしました

client_timeout = 3600

検索を再開しました

systemctl restart searchd

それでも私は同じ問題に直面しています。

では、アクティビティが長時間存在しない場合、どうすればスフィンクスサーバーを停止させることができますか?


詳細情報が追加されました -

一度に 50k チャンクで mysql からデータを取得し、while ループを実行して各行をフェッチし、sphinx RT インデックスで更新します。このような

//6mil rows update in mysql, so it takes around 18-20 minutes to complete this then comes this following part.

$subset_count = 50000 ;

$total_count_query = "SELECT COUNT(*) as total_count FROM content WHERE enabled = '1'" ;
$total_count = mysqli_query ($conn,$total_count_query);
$total_count = mysqli_fetch_assoc($total_count);
$total_count = $total_count['total_count'];

$current_count = 0;

while ($current_count <= $total_count){

$get_mysql_data_query = "SELECT record_num, views , comments, votes FROM content WHERE enabled = 1  ORDER BY record_num ASC LIMIT $current_count , $subset_count ";

//sphinx start transaction
mysqli_begin_transaction($sphinxql);

if ($result = mysqli_query($conn, $get_mysql_data_query)) {

    /* fetch associative array */
    while ($row = mysqli_fetch_assoc($result)) {

    //sphinx escape whole array
    $escaped_sphinx = mysqli_real_escape_array($sphinxql,$row);

    //update data in sphinx index
    $update_query_sphinx = "UPDATE $sphinx_index  
    SET 
        views       = ".$escaped_sphinx['views']." , 
        comments    = ".$escaped_sphinx['comments']." , 
        votes   = ".$escaped_sphinx['votes']." 
    WHERE 
        id          = ".$escaped_sphinx['record_num']." ";  

    mysqli_query ($sphinxql,$update_query_sphinx);

    }

    /* free result set */
    mysqli_free_result($result);
}
// Commit transaction
mysqli_commit($sphinxql);

$current_count = $current_count + $subset_count ;
}
4

2 に答える 2

1

直前にDBセッションを再接続または再起動する必要がありますmysqli_begin_transaction($sphinxql)

このようなもの。

<?php

//reconnect to spinx if it is disconnected due to timeout or whatever , or force reconnect
function sphinxReconnect($force = false) {
    global $sphinxql_host;
    global $sphinxql_port;
    global $sphinxql;
    if($force){
        mysqli_close($sphinxql);
        $sphinxql = @mysqli_connect($sphinxql_host.':'.$sphinxql_port,'','') or die('ERROR'); 
    }else{
        if(!mysqli_ping($sphinxql)){
            mysqli_close($sphinxql);
            $sphinxql = @mysqli_connect($sphinxql_host.':'.$sphinxql_port,'','') or die('ERROR'); 
        }
    }
}



//10mil+ rows update in mysql, so it takes around 18-20 minutes to complete this then comes this following part.

//reconnect to sphinx
sphinxReconnect(true);

//sphinx start transaction
mysqli_begin_transaction($sphinxql);

//do your otherstuff

// Commit transaction
mysqli_commit($sphinxql);
于 2015-09-23T06:43:04.510 に答える
1

したがって、ここにはいくつかの問題があり、どちらも大きなプロセスの実行に関連しています。

  1. MySQL server has gone away- これは通常、MySQL がタイムアウトしたこと意味しますが、メモリ不足のために MySQL プロセスがクラッシュしたことを意味する場合もあります。つまり、MySQL が応答を停止し、その理由をクライアントに通知しなかったことを意味します (つまり、ダイレクト クエリ エラーはありません)。1 回のトランザクションで 50k の更新を実行しているとのことですが、MySQL のメモリが不足している可能性があります。
  2. Allowed memory size of 134217728 bytes exhausted- PHPがメモリ不足であることを意味します。これは、MySQL がメモリ不足であるという考えにも信憑性をもたらします。

それで、これについて何をすべきか?

最初の一時しのぎの解決策は、PHP と MySQL のメモリ制限を増やすことです。それは根本的な原因を実際に解決するものではなく、デプロイ スタックをどの程度制御できるか (および持っている知識) によっては、それが不可能な場合があります。

数人が言及したように、プロセスをバッチ処理すると役立つ場合があります。解決しようとしている実際の問題を知らずに、これを行う最善の方法を言うのは困難です。たとえば、バッチで 50000 件ではなく 10000 件または 20000 件のレコードを計算できれば、問題を解決できる可能性があります。1 つのプロセスで時間がかかりすぎる場合は、メッセージ キューの使用を検討することもできます ( RabbitMQは、私が多くのプロジェクトで使用した優れたものです)。これにより、複数のプロセスを同時に実行できます。小さいバッチの処理。

計算を実行するために 600 万件以上のレコードすべての知識が必要な場合は、プロセスをいくつかの小さなステップに分割し、「現在までに」行われた作業を (そのように) キャッシュしてから、ピックアップすることができます。次のプロセスの次のステップ。これをきれいに行う方法は難しいです (繰り返しますが、RabbitMQ のようなものは、各プロセスが終了したときにイベントを発生させて次のプロセスを開始できるようにすることで、これを単純化できます)。

つまり、要するに、最良の 2 つのオプションがあります。

  1. 可能な限り多くのリソース/メモリを問題に投入します
  2. 問題をより小さな自己完結型のチャンクに分割します。
于 2015-09-23T01:16:45.927 に答える