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をinsertステートメントに置き換えても、メモリはリークしません。
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ビットのpython2.7.2(Python(x、y)2.7.2.3に付属)を使用しており、.exeインストーラーを使用してpyodbc32ビット3.0.6を手動でインストールしています。ああ、私はMySQL5.5.1732ビットを使用しています。
誰かが以前にこの問題に遭遇したことがありますか?コメントをいただければ幸いです。どうもありがとう!
ああ、selectステートメントの後にコミットする理由は、SQL操作のラッパーを書いているからだと言うのを忘れていました。ステートメントからそれが選択であるか挿入であるかを判断できないため、すべてが完了したことを確認するために、すべてのステートメントをフェッチしてコミットします。選択/挿入/更新/表示を区別する良い方法があれば、このメモリリークの問題を回避できると思います。