记一次Django相关的内存溢出问题排查过程

内存溢出问题排查

前言

    系统中需要运行一个脚本,脚本中通过项目配置,会调用Django的model,而且脚本中是一个轮询机制,会不断的查库操作,公司内部监控平台爆出服务器内存占用过高,排查到该脚本。

问题

内存无法释放,持续增长

  1. 分析内存工具,tracemalloc 工具包;

分析过程

1.代码

import tracemalloc
class Ticker(object):
	def __init__(self):
		pass
	def run(self):
		""""逻辑块"""
        a = tracemalloc.take_snapshot()
        e = a.compare_to(c, "lineno")
        for elem in e[0:10]:
                elem = r"{}".format(elem)
                sub = re.search(r".*\\(.*)\\(.*):.*: (size=.*), count.*", elem)
                if sub is None:
                    print(elem)
                elif "tracemalloc.py" == sub.group(2):
                    pass
                else:
                    print(sub.group(1), sub.group(2), "----", sub.group(3))
        print("++++++++++++++++++++++++++++++++++++++++")
if __name__ == '__main__':
    T = Ticker()
    tracemalloc.start()
    c = tracemalloc.take_snapshot()
    while True:
        asd = r.get("ht_mq_power")
        if asd == "0":
            print("redis  ht mq_power off")
            sys.exit()
        T.run()
        time.sleep(0.3)

2.》》》运行结果

<frozen importlib._bootstrap_external>:487: size=101 KiB (+101 KiB), count=1040 (+1040), average=100 B
redis connection.py ---- size=64.1 KiB (+64.1 KiB)
fields related.py ---- size=21.9 KiB (+21.9 KiB)
utils functional.py ---- size=14.7 KiB (+14.7 KiB)
models options.py ---- size=10.7 KiB (+10.7 KiB)
lib _weakrefset.py ---- size=10104 B (+10104 B)
models expressions.py ---- size=8736 B (+8736 B)
pymqi __init__.py ---- size=8584 B (+8584 B)
lib _weakrefset.py ---- size=8512 B (+8512 B)
++++++++++++++++++++++++++++++++++++++++
<frozen importlib._bootstrap_external>:487: size=101 KiB (+101 KiB), count=1040 (+1040), average=100 B
redis connection.py ---- size=64.1 KiB (+64.1 KiB)
fields related.py ---- size=23.2 KiB (+23.2 KiB)
utils functional.py ---- size=14.7 KiB (+14.7 KiB)
models options.py ---- size=10.7 KiB (+10.7 KiB)
lib _weakrefset.py ---- size=10104 B (+10104 B)
models expressions.py ---- size=8808 B (+8808 B)
pymqi __init__.py ---- size=8584 B (+8584 B)
lib _weakrefset.py ---- size=8512 B (+8512 B)

3.分析
通过运行上面段的代码,会发现不断打印出每一次轮询内存占用详情,
(sub.group(1), sub.group(2), “----”, sub.group(3),
这里的:sub.group(1), sub.group(2) 代表的是哪个文件内存占用问题,
sub.group(3) 代表的是占用大小
分析出来: 1.models expressions.py这个文件占用会随着轮询次数的增长越来越大,联想到是否是Django的惰性加载机制,也就是会将查询SQL进行缓存,
2.fields related.py这个文件内存占用一样越来越大,这个是一个Django外键的文件,是否在逻辑块内有对象循环引用导致,Python的垃圾回收机制无法回收,所以引用gc模块,手动删除创建的每个Django查询对象,并主动进行垃圾回收
4.验证
通过在逻辑块中加入查询执行SQL代码:from django.db import connection import gc """"逻辑代码""" print(connection.queries)
5.结论
事实上打印的SQL一直在递增,都是之前的执行SQL累加在一个list里面

解决方案

from django import db
def func():
	"""logic code"""
	obj = Model.object.get(id=123)
	del obj
	gc.collect()
	db.reset_queries()  # 清除缓存的执行SQL
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值