標籤:指令碼 對象 讀取資料 code 同事 析構 檔案 有用 str
如果對您有用記得關注,更多乾貨。
今天上午剛到公司,就有同事在公司群裡反映某個計劃任務出現問題了。我就懷著刨根問底的心,去查看了log。發現挺有意思的一個問題,PHP記憶體溢出導致指令碼執行失敗。那就一起來看個究竟吧!
首先查看了計劃任務的Log
從報錯資訊字面意思可以看出,允許的134217728 bytes的記憶體已經用盡,還要試圖分配12961640 bytes
記憶體。
給你(當前指令碼)分配的記憶體你已經用完了,你還想問系統要記憶體。系統這時想對你說:
地主家也沒有餘糧啊(借用葛優大爺的一句話)
類比一下"案發現場"
分析"事故"原因
指令碼一次性讀取了大量的資料(可能是讀的檔案,可能是讀取的資料庫)
如: 往杯子(分配給當前指令碼的記憶體)裡面倒數水(log檔案的資料),杯子容量(記憶體)不夠用
解決方案
a. 既然杯子小 就換個大杯子(增大給指令碼分配的記憶體)治標不治本: ini_set(‘memory_limit‘,‘100M‘);
b. 把水分批次倒入杯子中(迴圈,分段讀取資料,讀資料庫的話可以用limit)
看看結果
分段讀取也是可以解決問題滴
其他最佳化方案
應當儘可能減少靜態變數的使用,在需要資料重用時,可以考慮使用引用(&)。
資料庫操作完成後,要馬上關閉串連;
一個對象使用完,要及時調用解構函式(__destruct())
用過的變數及時銷毀(unset())掉
可以使用memory_get_usage()函數,擷取當前佔用記憶體 根據當前使用的記憶體來調整程式
unset()函數只能在變數值佔用記憶體空間超過256位元組時才會釋放記憶體空間。(PHP核心的gc記憶體回收機制決定)
有當指向該變數的所有變數(如引用變數)都被銷毀後,才會釋放記憶體
(PHP變數底層實現是一個_zval_struct結構體,is_ref__gc表示引用計數 is_ref__gc表示是否為引用)
記因PHP的記憶體溢出導致的事故之解決