我遇到pyodbc的内存泄漏问题。我花了很长时间才找到。最后,我得到了内存泄漏发生的代码。
import pyodbc
conn = pyodbc.connect(myconnstr)
cur = conn.cursor()
for i in range(1000000):
print i
cur.execute('select * from test.aa;')
cur.fetchall()
cur.commit()
如果我运行这段代码,它会以每秒5mb的速度慢慢消耗内存。但是,如果我像下面这样删除最后一行,它不会泄漏内存。在迭代中关闭游标和连接并没有帮助。如果发生内存泄漏,关闭游标和连接将无法收回内存。
import pyodbc
conn = pyodbc.connect(myconnstr)
cur = conn.cursor()
for i in range(1000000):
print i
cur.execute('select * from test.aa;')
cur.fetchall()
但是,如果我用插入语句替换select,它不会泄漏内存:
import pyodbc
conn = pyodbc.connect(myconnstr)
cur = conn.cursor()
for i in range(1000000):
print i
cur.execute('insert into test.aa values(1);')
cur.commit()
我试着用孔雀鱼来追踪泄漏,但没有帮助。使用hpy().heap()得到以下结果:
Partition of a set of 286322 objects. Total size = 22433376 bytes.
Index Count % Size % Cumulative % Kind (class / dict of class)
0 115601 40 8825424 39 8825424 39 str
1 69891 24 3030424 14 11855848 53 tuple
2 1921 1 1352588 6 13208436 59 dict (no owner)
3 1074 0 1349016 6 14557452 65 dict of PyQt4.QtCore.pyqtWrapperType
4 477 0 1189980 5 15747432 70 dict of module
5 12326 4 887472 4 16634904 74 types.CodeType
6 12178 4 730680 3 17365584 77 function
7 1162 0 565496 3 17931080 80 dict of type
8 1162 0 523384 2 18454464 82 type
9 1074 0 502632 2 18957096 85 PyQt4.QtCore.pyqtWrapperType
<1140 more rows. Type e.g. '_.more' to view.>
它说只占用了22mb内存,但实际上python进程目前占用了500mb内存。
我使用32位python 2.7.2(随python (x,y) 2.7.2.3一起提供),并使用.exe安装程序手动安装pyodbc 32位3.0.6。噢,我用的是MySQL 5.5.17 32位。
以前有人遇到过这个问题吗?任何评论都是非常感谢的。很多谢谢!
哦,我忘了告诉你我在select语句之后提交的原因是我在为sql操作写一个包装器。我不能从语句中判断它是选择还是插入,所以我对每个语句都取取并提交,只是为了确保一切都完成了。如果有一个很好的方法来区分select/insert/update/show,我想我可以避免这个内存泄漏问题。
我还没有找到修复,但确实找到了一个解决方案。我只在一些机器上遇到了这个问题。在你的代码片段的帮助下,我能够缩小这些问题的范围,然后注意到所有这些问题都发生在使用5.2版本的MySQL ODBC连接器的地方,而那些没有泄漏的地方使用5.1。这在Windows和Linux上都发生过。
在有泄漏的机器上降级到5.1似乎已经解决了(或至少避免了)这个问题。