Django bulk_create ignore_conflicts=真正的泄漏内存

Django bulk_create ignore_conflicts=True leaks memory

我们正在使用 Django 2.2、python 3.6 和 mysql 5.6 来安排数据密集型作业。

长时间 运行 作业的内存会随着时间的推移而增加。 DEBUG=False 在 settings.py

为什么要使用ignore_conflicts?

我们为table设置了一个唯一键,所以ignore_conflicts可以过滤掉那些已经在table中的记录。

像这样的简单代码

for record_batch in readFromSomewhere(batch_size):
    for record in record_batch:
        product = parse(record)
        product_list.append(product)
    
    # memory increase and leak
    Product.objects.bulk_create(product_list, ignore_conflicts=True) 
    
    # memory does not increase
    #Product.objects.bulk_create(product_list)  

    #db.reset_queries()
    #gc.collect()

我看了很多Whosebugpost,放了gc.collect()django.db.reset_query(),但不妨碍增加。 如果我使用 Product.objects.bulk_create(products),内存不会增加。 但是如果我使用 Product.objects.bulk_create(products,ignore_conflicts=True) 内存会随着时间的推移而增加。

批量很小,100 左右。 我注意到批处理大小是否更小,这意味着 bulk_create 调用的数量更大,内存增加得更快。如果批大小较大,则内存增加较慢。

有没有想过在批处理创建(ignore_conflict=True)后释放内存到数据库中?

通过深入挖掘内存找到了根本原因。 我们使用的是 mysqlclient==1.3.14 包。该软件包包含警告检查。 这些警告消息已保存到内存中,永远不会被垃圾收集。

他们在新版本发布后直接从包中删除了所有警告检查。 所以升级到mysqlclient==1.4.4后内存变稳定了