例如
// 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致命错误并且死了.
in script.PHP,line 502 is MysqLi_query($sphinxql,$update_query_sphinx);
所以我的猜测是,狮身人面像服务器关闭/死亡几个小时/分钟后不活动.
我已经尝试在sphinx.conf中设置
client_timeout = 3600
重新启动searchd
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 ; }
> MysqL服务器已经消失 – 这通常意味着MysqL已经超时,但也可能意味着MysqL进程因内存不足而崩溃.简而言之,这意味着MysqL已经停止响应,并没有告诉客户端为什么(即没有直接的查询错误).看到你说你在一个事务中运行了50k的更新,很可能MysqL刚刚跑出内存.
>允许的内存大小为134217728字节耗尽 – 意味着PHP内存不足.这也导致了MysqL失去记忆的想法.
那么该怎么办呢?
最初的间接解决方案是增加PHP和MysqL的内存限制.这不是真正解决根本原因,并且取决于您拥有的部署堆栈的控制量(和知识),这可能是不可能的.
正如少数人提到的,批处理过程可能会有所帮助.在不知道您正在解决的实际问题的情况下,很难说出最好的方法.如果可以计算出1000000或20000个记录,一批50000个可能会解决您的问题.如果在一个过程中花费的时间太长,您还可以查看使用消息队列(RabbitMQ是一个很好的项目,我已经在许多项目中使用),以便您可以同时运行多个进程处理较小的批次.
如果您正在做一些需要所有600万条记录的知识来执行计算的内容,那么您可能会将该过程分解成若干较小的步骤,将完成的工作“缓存”至此为止“(如此),然后选择下一步的下一步.如何干净地做到这一点很困难(再次,像RabbitMQ这样的事情可以通过在每个进程完成时触发一个事件来简化,以便下一个可以启动).
那么简而言之就是你最好的两个选择:
>可以在任何地方的问题上投入更多的资源/内存将问题分解成较小的自给自足的大块.