3

我遇到了 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()

我尝试使用 guppy 来追踪泄漏,但它没有帮助。使用 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 位。

有没有人遇到过这个问题?任何意见都非常感谢。非常感谢!

哦,我忘了告诉我在选择语句之后提交的原因是我正在为 sql 操作编写一个包装器。我无法从语句中判断它是选择还是插入,因此我为每个语句获取并提交,以确保一切都已完成。如果在 select/insert/update/show 之间有一个好的方法来区分,我想我可以避免这个内存泄漏问题。

4

1 回答 1

0

我还没有找到解决方法,但确实找到了解决方法。我只在我们的一些机器上遇到了这个问题。在您的代码片段的帮助下,我能够缩小这些是哪些,然后注意到它确实发生在使用 MySQL ODBC 连接器版本 5.2 的地方,而那些它没有泄漏的地方使用5.1。这发生在 Windows 和 Linux 上。

在有泄漏的机器上降级到 5.1 似乎已经解决(或至少避免了)问题。

于 2013-01-21T17:12:51.217 回答