gpt4 book ai didi

Python MySQLdb 模块内存泄漏

转载 作者:可可西里 更新时间:2023-11-01 07:02:36 28 4
gpt4 key购买 nike

流行的 python mysql 模块“MySQLdb”似乎有内存泄漏问题。这是代码:

conn = MySQLdb.connect(...)
cursor = conn.cursor(cursorclass = MySQLdb.cursors.DictCursor)
sql = "select * from `test`"
cursor.execute(sql) #leak start
cursor.close()
conn.close()
time.sleep(20)

假设 test 是一个包含十亿条记录的表。我运行了 python 代码并执行

ps aux | awk '{print $2, $4, $11}' | grep python

同时,结果是内存使用增加到 47.0% 并且再也回不去了,即使我关闭了游标和 conn。有什么想法吗?

最佳答案

this post , Fredrik Lundh 解释了为什么内存可能不会返回给系统,即使这不是内存泄漏。在底部附近,他解释了为什么(在 Python2 中)range(50*1024*100) 可能会消耗大量内存,即使在删除列表后也不会被释放。他提到使用 xrange 是一种从一开始就避免内存问题的方法。

同样,使用 SSDictCursor 而不是 DictCursor 可能是避免内存问题的一种方法。SSDictCursor 使 MySQL 服务器将结果集保留在服务器端,游标将仅在需要时一次从结果集中获取行:

import MySQLdb
import MySQLdb.cursors as cursors
conn = MySQLdb.connect(..., cursorclass=cursors.SSDictCursor) #1
cursor = conn.cursor()
cursor.execute('select * from test') #2
for row in cursor: #3
print(row)
conn.close()
  1. 注意连接调用中的 cursorclass=cursors.SSDictCursor
  2. 使用 DictCursor(或任何非 SS 游标),调用 execute 会导致 MySQLdb将整个结果集加载到 Python 对象(例如字典列表)中。
  3. 使用 SSDictCursorMySQLdb 一次检索一行。

所以这将避免内存堆积问题,前提是您不需要一次性将整个结果集保存在 Python 中。

另请注意,当使用 SSCursorSSDictCursor 时,“无法在连接 until the entire result set has been fetched. 上发出新查询” 来自两个不同连接的游标可以同时使用.这对您来说可能不是问题,但需要注意。

您可能还想查看 oursql ,MySQL 的替代数据库适配器。 oursql 游标是服务器端游标,fetch lazily by default .

关于Python MySQLdb 模块内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22657993/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com