欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

PHP內存溢出的解決方法詳解

 更新時間:2022年07月19日 10:56:34   作者:PHP開源社區(qū)  
內存溢出是指應用系統(tǒng)中存在無法回收的內存或使用的內存過多,最終使得程序運行要用到的內存大于虛擬機能提供的最大內存。本文為大家總結了PHP內存溢出的解決方法,需要的可以參考一下

什么是內存溢出

內存溢出是指應用系統(tǒng)中存在無法回收的內存或使用的內存過多,最終使得程序運行要用到的內存大于虛擬機能提供的最大內存。

引起內存溢出的原因有很多種,常見的有以下幾種:

1 內存中加載的數據量過于龐大,如一次從數據庫取出過多數據;

2 集合類中有對對象的引用,使用完后未清空;

3 代碼中存在死循環(huán)或循環(huán)產生過多重復的對象實體;

4 使用的第三方軟件中的BUG;

5 啟動參數內存值設定的過??;

下面來看些在開發(fā)中經常遇到的內存溢出的實例

內存溢出經常報錯的情況

PHP Fatal error: Allowed memory size of 268 435 456 bytes exhausted

1.處理數組時出現內存溢出

1)使用迭代生成器,可以通過繼承Iterator接口實現

2)使用關鍵詞yield

function?xrange($start,?$end,?$step?=?1)?{
????for?($i?=?$start;?$i?<=?$end;?$i?+=?$step)?{
????????yield?$i;
????}
}

foreach?(xrange(1,?1000000)?as?$num)?{
????echo?$num,?"\n";
}

2.使用sql查詢數據,查出來很多,導致內存溢出

sql語句在mysql中可以查詢,但是使用php程序查詢就報php內存溢出

1)這個問題在php的官方網站叫緩沖查詢和非緩沖查詢。php的查詢缺省模式是緩沖模式。也就是,查詢數據結果一次全部提取到內存里供php程序額外的功能,比如說,計算行數,將指針指向某一行等。

更重要的是程序對數據集反復進行二次查詢和過濾操作。但這種緩沖查詢模式的缺陷是消耗內存,也就是用空間換速度。

2)另外一種查詢模式是非緩沖查詢,數據庫服務器會一條一條的返回數據,而不是一次全部返回,這樣的結果是php程序消耗較少的內存,但卻增加了數據庫服務器的壓力,因為數據庫會一直等待php來取數據,一直到數據全部取完。

1.首先查詢數據庫需要進行l(wèi)imit進行分頁查詢

2.如果不使用limit,使用非緩沖查詢

1.mysql:

$conn?=?mysql_connect("localhost",?"user",?"pass");
$db???=?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;
???}
}

2.pdo_mysql:

$pdo?=?new?PDO("mysql:host=localhost;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;
???}
}

3.mysqli:

$mysqli??=?new?mysqli("localhost",?"user",?"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();

3.假定日志中存放的記錄數為500000條,那么解決方案如下

ini_set(‘memory_limit’,’64M’); //重置php可以使用的內存大小為64M,一般在遠程主機上是不能修改php.ini文件的,只能通過程序設置。

注:在safe_mode(安全模式)下,ini_set失效

set_time_limit(600);//設置超時限制為6分鐘
$farr?=?$Uarr?=?$Marr?=?$IParr?=?$data?=?$_sub?=?array();
$spt?=?”$@#!$”;
$root?=?”/Data/webapps/VisitLog”;
$path?=?$dpath?=?$fpath?=?NULL;
$path?=?$root.”/”.date(“Y-m”,$timestamp);
$dpath?=?$path.”/”.date(“m-d”,$timestamp);

for($j=0;$j<24;$j++){
????$v?=?($j?<?10)???”0″.$j?:?$j;
????$gpath?=?$dpath.”/”.$v.”.php”;

????if(!file_exists($gpath)){
????????continue;

????}?else?{
????????$arr?=?file($gpath);////將文件讀入數組中
????????array_shift($arr);//移出第一個單元-》
????????$farr?=?array_merge($farr,$arr);
????????unset($arr);
????}
}

if(empty($this->farr)){
????echo?”沒有相關記錄!”;
????exit;
}

while(!empty($farr)){
????$_sub?=?array_splice($farr,?0,?10000);?//每次取出$farr中1000個
????for($i=0,$scount=count($_sub);$i<$scount;$i++){
????????$arr?=?explode($spt,$_sub[$i]);
????????$Uarr[]?=?$arr[1];?//vurl
????????$Marr[]?=?$arr[2];?//vmark
????????$IParr[]?=?$arr[3].”?|$nbsp;”.$arr[1];?//IP
????}
????unset($_sub);//用完及時銷毀
}
unset($farr);

這里,不難看出,一方面,我們要增加PHP可用內存大小,另一方面,只要我們想辦法對數組進行分批處理,分而治之,將用過的變量及時銷毀(unset),一般是不會出現溢出問題的。

4.上傳excel文件時,出現內存溢出的情況

在文件中分配大點的內存設置內存治標不治本,而且服務器的php.ini(memory_limit =128M)有時候是很難改的。所以在文件中設置。但是只有php.ini中的安全模式safe_mode開啟時才可以設置

ini_set('memory_limit',?'521M');

解決方法:

protected?/extensions/ExcelHelper.php?中945行?
$PHPReader->setReadDataOnly(true);??//在拿到數據后進行設置只讀

????public?static?function?importFromExcel($filePath,?$blankRowDel?=?false)
????{
????????set_time_limit(90);
????????Yii::import('application.extensions.phpexcel.PHPExcel');
????????$PHPExcel?=?new?PHPExcel();
????????//默認用excel2007讀取excel,若格式不對,則用之前的版本進行讀取
????????$PHPReader?=?new?PHPExcel_Reader_Excel2007();
????????if?(!$PHPReader->canRead($filePath))?{
????????????$PHPReader?=?new?PHPExcel_Reader_Excel5();
????????????if?(!$PHPReader->canRead($filePath))?{
????????????????throw?new?Exception('can?not?read?the?excel?file');
????????????}
????????}
????????$PHPReader->setReadDataOnly(true);

????????$PHPExcel??????=?$PHPReader->load($filePath);
????????$allSheetCount?=?$PHPExcel->getSheetCount();
????????$excelData?????=?array();
????????for?($currentSheetNum?=?0;?$currentSheetNum?<?$allSheetCount;?$currentSheetNum++)?{
????????????//讀取excel文件中的第一個工作表
????????????$currentSheet?=?$PHPExcel->getSheet($currentSheetNum);
????????????//取得當前表名
????????????$currentSheetTitle?=?$currentSheet->getTitle();
????????????//取得最大的列號
????????????$allColumn?=?$currentSheet->getHighestColumn();
????????????//取得一共有多少行
????????????$allRow?=?$currentSheet->getHighestRow();
????????????//?從第一行獲取列名
????????????$currentRow?=?1;
????????????//?從第A列開始輸出
????????????$colunmNameArray?=?array();
????????????$max_column_num??=?PHPExcel_Cell::columnIndexFromString($allColumn);
????????????for?($current_column_num?=?0;?$current_column_num?<=?$max_column_num;?$current_column_num++)?{
????????????????$currentColumn?=?PHPExcel_Cell::stringFromColumnIndex($current_column_num);
????????????????$val???????????=?$currentSheet->getCellByColumnAndRow($current_column_num,?$currentRow)->getValue();
????????????????if?(empty($val))?{
????????????????????continue;
????????????????}
????????????????if?(is_object($val))?{
????????????????????$colunmNameArray[$currentColumn]?=?'';
????????????????????foreach?($val->getRichTextElements()?as?$cell)?{
????????????????????????$colunmNameArray[$currentColumn]?.=?$cell->getText();
????????????????????}
????????????????}?else?{
????????????????????$colunmNameArray[$currentColumn]?=?$val;
????????????????}
????????????}

????????????//從第二行開始輸出,因為excel表中第一行為列名
????????????$sheetData?=?array();
????????????for?($currentRow?=?2;?$currentRow?<=?$allRow;?$currentRow++)?{
????????????????//從第A列開始輸出?*/
????????????????$rowData???=?array();
????????????????$blankCell?=?0;
????????????????for?($current_column_num?=?0;?$current_column_num?<=?$max_column_num;?$current_column_num++)?{
????????????????????$currentColumn?=?PHPExcel_Cell::stringFromColumnIndex($current_column_num);
????????????????????$val???????????=?$currentSheet->getCellByColumnAndRow($current_column_num,?$currentRow)->getValue();
????????????????????if?(!isset($colunmNameArray[$currentColumn]))?{
????????????????????????continue;
????????????????????}
????????????????????//如果輸出漢字有亂碼,則需將輸出內容用iconv函數進行編碼轉換,如下將gb2312編碼轉為utf-8編碼輸出
????????????????????if?(is_object($val))?{
????????????????????????$rowData[$currentColumn]?=?'';
????????????????????????foreach?($val->getRichTextElements()?as?$cell)?{
????????????????????????????$rowData[$currentColumn]?.=?$cell->getText();
????????????????????????}
????????????????????}?else?{
????????????????????????$rowData[$currentColumn]?=?$val;
????????????????????}

????????????????????if?(empty($rowData[$currentColumn]))?{
????????????????????????$blankCell++;
????????????????????}
????????????????}

????????????????if?(!$blankRowDel?||?chr($blankCell?+?64)?!=?$allColumn)?{
????????????????????$sheetData[]?=?$rowData;
????????????????}
????????????}

????????????$excelData[$currentSheetTitle]?=?array(
????????????????'header'??=>?$colunmNameArray,
????????????????'content'?=>?$sheetData,
????????????);
????????}
????????return?$excelData;
????}

到此這篇關于PHP內存溢出的解決方法詳解的文章就介紹到這了,更多相關PHP內存溢出內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

最新評論