我正在使用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之类的方法可以通过在每个进程完成后触发一个事件来简化该过程,以便下一个进程可以启动)。
简而言之,最好的两个选择是: