PHP命令执行PHP脚本,结束之前,清理内存命令会回收吗

解决PHP里大量数据循环时内存耗尽的方法
转载 &更新时间:日 11:25:39 & 投稿:mrr
错误信息提示最大内存已经耗尽,该如何解决呢?下面小编给大家解决PHP里大量数据循环时内存耗尽的问题,需要的朋友可以参考下
最近在开发一个PHP程序的时候遇到如下一问题:
PHP Fatal error: Allowed memory size of 268 435 456 bytes exhausted
错误信息显示允许的最大内存已经耗尽。遇到这样的错误起初让我很诧异,但转眼一想,也不奇怪,因为我正在开发的这个程序是要用一个foreach循环语句在一个有4万条记录的表里全表搜索具有特定特征的数据,也就是说,一次要把4万条数据取出,然后逐条检查每天数据。可想而知,4万条数据全部加载到内存中,内存不爆才怪。
毕竟编程这么多年,我隐约记得PHP里提供有非一次全部加载数据的API,是像处理流媒体那样,随用随取随丢、数据并不会积累在内存的查询方法。经过简单的搜索,果然在官方网站上找到的正确的用法。
这个问题在PHP的官方网站上叫缓冲查询和非缓冲查询(Buffered and Unbuffered queries)。 PHP的查询缺省模式是缓冲模式。也就是说,查询数据结果会一次全部提取到内存里供PHP程序处理。这样给了PHP程序额外的功能,比如说,计算行数,将 指针指向某一行等。更重要的是程序可以对数据集反复进行二次查询和过滤等操作。但这种缓冲查询模式的缺陷就是消耗内存,也就是用空间换速度。
相对的,另外一种PHP查询模式是非缓冲查询,数据库服务器会一条一条的返回数据,而不是一次全部返回,这样的结果就是PHP程序消耗较少的内存,但却增加了数据库服务器的压力,因为数据库会一直等待PHP来取数据,一直到数据全部取完。
很显然,缓冲查询模式适用于小数据量查询,而非缓冲查询适应于大数据量查询。
对于PHP的缓冲模式查询大家都知道,下面列举的例子是如何执行非缓冲查询API。
非缓冲查询方法一: mysqli
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");
$uresult = $mysqli-&query("SELECT Name FROM City", MYSQLI_USE_RESULT);
if ($uresult) {
while ($row = $uresult-&fetch_assoc()) {
echo $row['Name'] . PHP_EOL;
$uresult-&close();
非缓冲查询方法二: pdo_mysql
$pdo = new PDO("mysql:host=dbname=world", 'my_user', 'my_pass');
$pdo-&setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
$uresult = $pdo-&query("SELECT Name FROM City");
if ($uresult) {
while ($row = $uresult-&fetch(PDO::FETCH_ASSOC)) {
echo $row['Name'] . PHP_EOL;
非缓冲查询方法三: mysql
$conn = mysql_connect("localhost", "my_user", "my_pass");
= mysql_select_db("world");
$uresult = mysql_unbuffered_query("SELECT Name FROM City");
if ($uresult) {
while ($row = mysql_fetch_assoc($uresult)) {
echo $row['Name'] . PHP_EOL;
以上内容就是小编给大家分享的解决PHP里大量数据循环时内存耗尽的方法,希望对大家有所帮助。
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具php return会结束脚本吗_百度知道
php return会结束脚本吗
我有更好的答案
如果return 是在方法或者函数里,不会结束脚本运行,只是返回当前的内容,该方法里下面的代码不再执行,这个较为常见;如果return在方法外面,会结束当前return所在文件的脚本运行,并不影响其它的调用脚本,这个一般用在配置文件里,直接返回一个配置数组之类的。
采纳率:41%
return终止函数的执行和从函数中返回一个值,通常是一个方法里面,把这个方法执行完毕,把最后的结果返回给这个方法。其实就是纯粹的返回值了,但是也不会运行后续代码,不能说是会结束脚本,看代码环境。return不会像exit那样,直接退出进程,停止运行
为您推荐:
其他类似问题
return的相关知识
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。PHP内存释放有关的操作
1、&符号的影响
显式引用一个变量,会增加该内存的引用计数:
$a = "something";
此时unset($a), 但是仍有$b指向该内存区域的引用,内存不会释放。
2、unset函数的影响
unset只是断开一个变量到一块内存区域的连接,同时将该内存区域的引用计数-1;但是在循环体内部,例如:$a=new A(); unset($a);并不会将$a的引用计数减到零;
3、对变量赋null值操作的影响;
$a = null 是直接将$a 指向的数据结构置空,同时将其引用计数归0。
4、脚本执行结束的影响
脚本执行结束,该脚本中使用的所有内存都会被释放,不论是否有引用环。
那么以上介绍了这么多和内存有关的东西,但是内存的回收都是由PHP的垃圾回收进程来进行的。当然你也可以像写C一样,自己手动回收进程,对所使用的变量进行null赋值。但这样会增加了程序的复杂度,而一般对于PHP来说不建议这样做,如果像你的问答里说的,在处理大量和运行时间长的代码里,那最好还是手动去销毁一些不使用的变量。并且可以通过memory_get_usage和memory_get_peak_usage等函数监测内存的使用情况。
没有更多推荐了,
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!下次自動登錄
現在的位置:
& 綜合 & 正文
PHP命令執行PHP腳本,結束之前,內存會回收嗎?
在往下看之前,如果你不明白什麼是GC (Garbage Collection) 的話,那一定要先去了解GC,不然你根本不知道我在說什麼!
http://www.php.net/manual/en/features.gc.php
http://blog.csdn.net/phpkernel/article/details/5734743
===================================================================
再詳細說下問題:
unix下,用php命令來執行php腳本,在php結束之前,內存有沒有機會被回收?新的GC有沒有機會被調用?
出現這個問題,是因為線上有個 離線數據導入腳本,需要把幾千萬行數據篩選入庫,發現,在執行過程中,到達一定程度,就會拋出 內存使用超過最大值。
Fatal error: Allowed memory size of
bytes exhausted
那第一想到的就是程序是不是有什麼bug,造成內存超出,看了半天沒有發現問題,於是,突然出現了這個疑問。 那要解決這個疑問,最好的辦法就去翻源碼吧。
在之前我這麼說:
都知道,PHP5.3有了新的垃圾回收機制:GC,它不是重點,不談它的原理。
經過翻閱PHP源碼,發現,調用這個的時機是在 main/main.c ::php_request_shutdown這個函數中,
zend_deactivate(TSRMLS_C);
php_request_shutdown,通過名字就能看出,它是在php請求結束的時候執行的,在這裡會執行 gc_collect_cycles 來清理內存。
其實這句話是沒錯,但它只針對於SAPI接口(之前我就錯在這個地方。),在用PHP命令執行php腳本的時候,是不會執行這個php_request_shutdown的。
那回到最初的問題,過程中到底有沒有執行GC呢?
為了更直觀有效的知道答案,我選擇了最BT,最暴力的方法,攔截gc_collect_cycles,輸出error_log到文件,只要執行了,
那肯定會輸出log來。
重新編譯PHP後,果不其然,符合官方的說法,只要buckets滿超過默認值1000,就會啟動GC來清理沒用的內存,防止內存泄露。
那問 “什麼時間 觸發的GC呢?”,答 “buckets超過1000的時候啊”,這不屁話嘛,要的是真真正正的執行流程,so。。不斷的debug,
不斷的grep,不斷的step,不斷的C+T,終於搞清楚了。下面就來根據官方的說法詳細談談,PHP到底是怎麼觸發的。
有一點要注意,PHP的命令入口 和 sapi接口的入口 是不同的,我就載在這個地方,以為都公用一個。
測試代碼以官方文檔為例:
public $var = '3.';
for ( $i = 0; $i &= 1000000; $i++ )
<div class="line number9 index8 alt2" style="height: 22 margin: 0px ! padding: 0px 1em ! border: 0px ! font-size: 1em ! vertical-align: baseline ! border-top-left-radius: 0px ! border-top-right-radius: 0px ! border-bottom-right-radius: 0px ! border-bottom-left-radius: 0px ! background-image: none ! bottom: auto ! float: none ! left: auto ! line-height: 1.8em ! outline: 0px ! overflow: visible !imp
【上篇】【下篇】

我要回帖

更多关于 回收电脑内存条 的文章

 

随机推荐