【问题标题】:Flask application memory leakage with sql alchemy使用 sql alchemy 烧瓶应用程序内存泄漏
【发布时间】:2020-06-27 11:31:48
【问题描述】:

我正在通过流式处理大型 http 响应内容(100 万条记录)。 从请求中读取 10000 个元素后,我正在调用一个方法将它们插入数据库,然后继续处理响应。我注意到 RAM 使用量在不断增加。 下面是示例代码。如果我评论 db.session.add() 部分尝试将数据添加到临时列表,则不会发生内存泄漏。那么 SQLAlchemy 在插入数据库后没有正确释放内存?请提出建议。

示例代码。

for chunk in response.iter_content(2048):
    #decode chunk
    xyz_json_list = list()
    xyz_json = json.loads(chunk_string)
    xyz_json_list.append(xyz_json)
    if len(xyz_json_list) == 10000:
        add_elements_to_db(xyz_json_list)
        xyz_json_list = list()
    ...



func add_elements_to_db(xyz_list):
    for xyz in xyz_list:
       db.sesssion.add(create_object_from_json(xyz))
    db.session.commit()
    db.session.expunge_all()
    del xyz_list
    gc.collect()

每次调用 add_elements_to_db 后,内存呈指数增长。

【问题讨论】:

    标签: python flask flask-sqlalchemy


    【解决方案1】:

    截至v1.0.0SQLAlchemy 支持Bulk Opertions

    • Session.bulk_save_objects()
    • Session.bulk_insert_mappings()
    • Session.bulk_update_mappings()
    s = Session()
    objects = [
        User(name="u1"),
        User(name="u2"),
        User(name="u3")
    ]
    s.bulk_save_objects(objects)
    

    这样您就可以对add_elements_to_db() 函数进行一些小改动:

    [..]
    
    def add_elements_to_db(xyz_list):
    
        objects = []
       
        for xyz in xyz_list:
            objects.append(create_object_from_json(xyz))
    
        db.session.bulk_save_objects(objects)
    
    [..]
    

    只是好奇,为什么你不使用 Redis 来执行异步任务,你可以将 add_elements_to_db() 函数作为异步任务的执行委托给 Redis,因为它是一个阻塞任务,而且速度特别慢,而且你肯定会看到一个很好的表现。

    【讨论】:

    • 感谢您的建议。我曾尝试使用 bulk_save_objects,但它并没有解决我在使用 SQLAlchemy 将对象添加到数据库后没有释放内存的问题。而且 bulk_save_objects 比添加单个对象并在最后进行提交花费更多的时间。我一直在寻找为什么添加到会话后的对象没有被垃圾收集和内存释放。它是一次性活动,所以不用担心性能。
    猜你喜欢
    • 2022-08-05
    • 2019-04-27
    • 1970-01-01
    • 2016-03-28
    • 2010-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多