摘要:發現挺有意思的一個問題,內存溢出導致腳本執行失敗。那就一起來看個究竟吧首先查看了計劃任務的從報錯信息字面意思可以看出,允許的的內存已經用盡,還要試圖分配內存。給你當前腳本分配的內存你已經用完了,你還想問系統要內存。
今天上午剛到公司,就有同事在公司群里反映某個計劃任務出現問題了。我就懷著刨根問底的心,去查看了log。發現挺有意思的一個問題,PHP內存溢出導致腳本執行失敗。那就一起來看個究竟吧!
首先查看了計劃任務的Log
從報錯信息字面意思可以看出,允許的134217728 bytes的內存已經用盡,還要試圖分配12961640 bytes內存。
給你(當前腳本)分配的內存你已經用完了,你還想問系統要內存。系統這時想對你說:
地主家也沒有余糧啊(借用葛優大爺的一句話)
模擬一下"案發現場"
新建一個mem_exhausted.php文件 copy過來一個2.4M的log文件做測試用
寫個簡單的腳本重現"案發現場" 故意分配1M的內存 來讀取2.4M的log
執行腳本,"案發現場"重現
分析"事故"原因
腳本一次性讀取了大量的數據(可能是讀的文件,可能是讀取的數據庫)
如下圖: 往杯子(分配給當前腳本的內存)里面倒數水(log文件的數據),杯子容量(內存)不夠用
解決方案
既然杯子小 就換個大杯子(增大給腳本分配的內存)治標不治本: ini_set("memory_limit","100M");
把水分批次倒入杯子中(循環,分段讀取數據,讀數據庫的話可以用limit)
看看結果
分段讀取也是可以解決問題滴
其他優化方案
應當盡可能減少靜態變量的使用,在需要數據重用時,可以考慮使用引用(&)。
數據庫操作完成后,要馬上關閉連接;
一個對象使用完,要及時調用析構函數(__destruct())
用過的變量及時銷毀(unset())掉
可以使用memory_get_usage()函數,獲取當前占用內存 根據當前使用的內存來調整程序
unset()函數只能在變量值占用內存空間超過256字節時才會釋放內存空間。(PHP內核的gc垃圾回收機制決定)
有當指向該變量的所有變量(如引用變量)都被銷毀后,才會釋放內存
(PHP變量底層實現是一個_zval_struct結構體,refcount_gc表示引用計數 is_ref__gc表示是否為引用)
-------------------------我是分割線-------------------------
硬廣時間(對Nginx感興趣的童鞋可以看下)Nginx系列課程索引
引子: WebServer與PHP通信姿勢
熟悉了解Nginx與PHP是怎么進行通信的
起手式: PHP程序猿應該知道的Nginx (上)
如何更好的使用Nginx和Nginx配置
進階式: PHP程序猿應該知道的Nginx (中)
深入理解Nginx內核和Nginx運行原理,剖析Nginx高性能的秘密
實戰篇: PHP程序猿應該知道的Nginx (下)
百聞不如一run 一起來開發一個Nginx的拓展
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/24936.html
摘要:發現挺有意思的一個問題,內存溢出導致腳本執行失敗。那就一起來看個究竟吧首先查看了計劃任務的從報錯信息字面意思可以看出,允許的的內存已經用盡,還要試圖分配內存。給你當前腳本分配的內存你已經用完了,你還想問系統要內存。 今天上午剛到公司,就有同事在公司群里反映某個計劃任務出現問題了。我就懷著刨根問底的心,去查看了log。發現挺有意思的一個問題,PHP內存溢出導致腳本執行失敗。那就一起來看個...
摘要:如何實現持久化持久化,將在內存中的的狀態保存到硬盤中,相當于備份數據庫狀態。相當于備份數據庫接收到的命令,所有被寫入的命令都是以的協議格式來保存的。 最近社區里面有一篇文章引起了最多程序猿的關注,Laravel、PHPer 面試可能會遇到的問題,看評論區不少小伙伴們被難倒,對于一些問題同樣難倒了我(其實有很多啦),趁著周末有空,又總結梳理了一遍,順便來答一波題。由于個人技術水平有限,答...
閱讀 634·2021-09-22 10:02
閱讀 6324·2021-09-03 10:49
閱讀 565·2021-09-02 09:47
閱讀 2151·2019-08-30 15:53
閱讀 2928·2019-08-30 15:44
閱讀 900·2019-08-30 13:20
閱讀 1812·2019-08-29 16:32
閱讀 889·2019-08-29 12:46