【问题标题】:MySQLdb - cursor - memory leak?MySQLdb - 游标 - 内存泄漏?
【发布时间】:2013-10-09 09:09:35
【问题描述】:

我在 Windows 7 上的 Python32 下使用 MySQLdb

Python 3.2.3 (default, Apr 11 2012, 07:12:16) [MSC v.1500 64 bit (AMD64)] on win32
>>> import MySQLdb as My
>>> My.version_info
(1, 2, 3, 'final', 0)

我正在运行的服务一遍又一遍地调用这个:

cursor = self._connection._conn.cursor()
cursor.execute(sql)
for i in cursor.fetchall(): pass # Operation that is not important
cursor.close()
gc.collect()
return set() # Will be filled with DB data

而且内存使用量只会越来越高,我已经尝试过diagnosing it 并得到了这样的结果:

83    23.129 MB     0.000 MB           cursor = self._connection._conn.cursor()
84    23.129 MB     0.000 MB           cursor.execute(sql)
85    23.137 MB     0.008 MB           for i in cursor.fetchall(): pass
86    23.137 MB     0.000 MB           cursor.close()
87
88    23.137 MB     0.000 MB           gc.collect()
89
90    23.137 MB     0.000 MB           return set()

__iter__ API 似乎都不是更好:

84    23.145 MB     0.000 MB           cursor.execute(sql)
85    23.145 MB     0.000 MB           for i in cursor: pass
86    23.152 MB     0.008 MB           cursor.close()
87
88    23.152 MB     0.000 MB           gc.collect()
89
90    23.152 MB     0.000 MB           return set()

也没有手动循环使用fetchone()

84    23.141 MB     0.000 MB           cursor.execute(sql)
85    23.141 MB     0.000 MB           while True:
86    23.141 MB     0.000 MB               row = cursor.fetchone()
87    23.141 MB     0.000 MB               if not row:
88    23.141 MB     0.000 MB                   break
89    23.148 MB     0.008 MB           cursor.close()
90
91    23.148 MB     0.000 MB           gc.collect()
92
93    23.148 MB     0.000 MB           return set()

那么为什么不将内存清理回23.129MB(为什么它总是使用新的 8KB)?光标有问题吗?我做错了吗?

【问题讨论】:

  • GC 模块有一个用于查看内存泄漏的调试接口,这会让您更深入了解吗?
  • @dwxw 它给了我很多我无法解释的信息,如果你能提供任何好的资源来使用gc 诊断这个,我会很高兴阅读它。跨度>

标签: python mysql python-3.x memory-leaks


【解决方案1】:

IIRC cursor.fetchall() 构建内存中的行列表,并且由于内存分配成本很高,Python 倾向于保留已分配的内存。尝试迭代您的光标,即for row in cursor: do_something_with(row)

【讨论】:

  • 我已经用不同的方法写下了编辑。总是一样的结果...+8KB
  • 加上gc.collect() 应该处理好这个,不是吗?
  • 我注意到在不使用cursor.fetchall() 的两种方法中,调用cursor.close() 时内存使用量会增加...您也许应该 1/ 在它自己的行上设置 pass 语句,然后 2/在调用cursor.close() 之前添加一些noop 语句。您还可以阅读 stackoverflow.com/questions/9617001/…stackoverflow.com/questions/1316767/… 以了解有关该主题的更多信息。最后请注意,虚拟内存管理是一个复杂的话题......但我假设你已经知道这一点
  • 呵呵,是的:如果内存被 cursor 对象本身使用,gc.collect() 不会收集它,因为您在当前命名空间。在cursor.close()gc.collect() 之间添加del cursor 可能是个好主意;)
猜你喜欢
  • 2014-08-09
  • 1970-01-01
  • 1970-01-01
  • 2016-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多