我正在使用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_limit并给了PHP Fatal error并死亡。
in script.php , line 502 is

mysqli_query($sphinxql,$update_query_sphinx);

所以我的猜测是, sphinx 服务器在闲置了数小时/数分钟后关闭/死了。

我已经尝试在sphinx.conf中设置
client_timeout = 3600

重新开始搜寻
systemctl restart searchd

而且我仍然面临着同样的问题。

那么,如果长时间没有事件,我怎么不能让 sphinx 服务器死在我身上呢?

添加了更多信息-

我一次从mysql中以50k块获取数据,并执行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 ;
}

最佳答案

因此,这里有两个问题,都与运行大流程有关。

  • MySQL server has gone away-这通常意味着MySQL已超时,但也可能意味着MySQL进程由于内存不足而崩溃。简而言之,这意味着MySQL已停止响应,并且没有告诉客户端原因(即没有直接查询错误)。就像您说的那样,您正在单个事务中运行5万个更新,这很可能就是MySQL内存不足。
  • Allowed memory size of 134217728 bytes exhausted-表示PHP内存不足。这也使人们相信MySQL内存不足。

  • 那么该怎么办呢?

    最初的权宜之计是增加PHP和MySQL的内存限制。这并不能真正解决根本原因,并且取决于您对部署堆栈的控制量(和您所拥有的知识),这可能是不可能的。

    如少数人所述,批处理可能会有所帮助。在不知道您要解决的实际问题的情况下,很难说出执行此操作的最佳方法。如果您可以计算出例如10000或20000的批次记录instad 50000,则可能会解决您的问题。如果在单个过程中花费太长的时间,您还可以考虑使用消息队列(RabbitMQ是我在多个项目中使用过的一个好队列),以便您可以同时运行多个过程处理较小的批次。

    如果您要执行的操作需要了解所有600万以上的记录才能执行计算,则可以将流程分成多个较小的步骤,“按时”缓存已完成的工作(如此),然后再进行选择下一步的下一步。如何做到这一点很困难(同样,RabbitMQ之类的方法可以通过在每个进程完成后触发一个事件来简化该过程,以便下一个进程可以启动)。

    简而言之,最好的两个选择是:
  • 随处可以在问题上投入更多资源/内存
  • 将问题分解为较小的自包含块。
  • 09-10 06:49
    查看更多