2013-10-09 4 views
1

Я использую MySQLdb под Python32 на Windows 7: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 (почему он всегда использует новый 8 КБ)? Является ли курсор ошибкой? Я делаю что-то неправильно?

+0

Модуль [GC] (http://docs.python.org/3.2/library/gc.html) имеет интерфейс отладки для поиска утечек памяти, что дает вам более глубокое понимание? – dwxw

+0

@dwxw Это дает мне много информации, которую я не могу интерпретировать, если вы можете предоставить любой хороший ресурс для диагностики этого с помощью 'gc', я буду рад его прочесть. – Vyktor

ответ

1

IIRC cursor.fetchall() строит список строк в памяти, и поскольку распределение памяти является дорогостоящим, Python имеет тенденцию сохранять выделенную память. Попробуйте вместо этого перебрать курсор, то есть for row in cursor: do_something_with(row).

+0

Я уже записывал редактирование разными способами. Всегда тот же результат ... '+ 8KB' – Vyktor

+0

Плюс' gc.collect() 'должен позаботиться об этом, не так ли? – Vyktor

+0

Я заметил, что в двух методах, не использующих 'cursor.fetchall()', использование памяти увеличивается при вызове 'cursor.close()' ... Вы должны, возможно, 1/установить утверждение pass на своей собственной строке и 2/добавьте инструкцию noop непосредственно перед вызовом 'cursor.close()'. Вы также можете прочитать http://stackoverflow.com/questions/9617001/python-garbage-collection-fails и http://stackoverflow.com/questions/1316767/how-can-i-explicitly-free-memory-in- python/для получения дополнительной информации по этой теме. Наконец, обратите внимание, что управление виртуальной памятью является сложной темой ... Но я предполагаю, что вы уже знаете это –

Смежные вопросы