我使用PHP和禁用AUTOCOMIT在bulk inserts
中进行RealTime Index
,
e.g。
// 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
我仍然面临同样的问题。
那么,如果长时间没有活动,我怎能不让狮身人面像服务器死在我身上?
添加了更多信息 -
我一次从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 ;
}
答案 0 :(得分:1)
所以这里有几个问题,都与运行大流程有关。
MySQL server has gone away
- 这个通常是意味着MySQL已超时,但也意味着MySQL进程因内存不足而崩溃。简而言之,这意味着MySQL已停止响应,并且没有告诉客户端原因(即没有直接查询错误)。看到你说你在一次交易中运行50k更新,可能是MySQL内存不足。Allowed memory size of 134217728 bytes exhausted
- 表示 PHP 内存不足。这也使得人们相信MySQL的内存不足。那该怎么办?
最初的间隙解决方案是增加PHP和MySQL的内存限制。这并不能解决根本原因,并且取决于您对部署堆栈的控制(以及您拥有的知识),可能无法实现。
正如一些人所提到的,批处理过程可能有所帮助。在不知道您正在努力解决的实际问题的情况下,很难说最好的方法。如果你可以计算一批可以解决问题的10000或20000个50000记录instad。如果在一个过程中花费太长时间,您还可以考虑使用消息队列(RabbitMQ是我在许多项目中使用过的好消息队列),所以您可以同时运行多个进程 处理较小的批次。
如果您正在做一些需要了解所有 600万条+记录来执行计算的事情,您可能会将该过程分成若干个较小的步骤,缓存完成的工作和#34;到目前为止#34; (如此),然后在下一个过程中选择下一步。如何干净利落地完成这项工作很困难(同样,像RabbitMQ这样的东西可以通过在每个流程完成时触发一个事件来简化它,以便下一个流程可以启动)。
因此,简而言之,有两个最佳选择:
答案 1 :(得分:1)
您需要在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);