Temel MySQLdb
imleci, tüm sorgu sonucunu sunucudan bir defada getirir. Bu, çok fazla bellek ve zaman tüketebilir. Büyük bir sorgu oluşturmak istediğinizde ve sunucudan sonuçları bir kerede çekerken, MySQLdb.cursors.SSCursor kullanın.
Dolayısıyla engine
oluştururken connect_args={'cursorclass': MySQLdb.cursors.SSCursor}
geçen deneyin:
from sqlalchemy import create_engine, MetaData
import MySQLdb.cursors
engine = create_engine('mysql://root:[email protected]/e2', connect_args={'cursorclass': MySQLdb.cursors.SSCursor})
meta = MetaData(engine, reflect=True)
conn = engine.connect()
rs = s.execution_options(stream_results=True).execute()
getirme tamamlanana kadar kullanarak SSCursor tabloyu kilitler olduğunu http://www.sqlalchemy.org/trac/ticket/1089
Not bakınız. Bu, aynı bağlantıyı kullanarak diğer imleçleri etkiler: Aynı bağlantıdan iki imleç, aynı anda tablodan okuyamaz. Bununla birlikte, farklı bağlantılardan gelen imleçler aynı tablodan eşzamanlı olarak okuyabilirler. oursql Python için MySQL bağlamaları alternatif setinden oluşması
import MySQLdb
import MySQLdb.cursors as cursors
import threading
import logging
import config
logger = logging.getLogger(__name__)
query = 'SELECT * FROM huge_table LIMIT 200'
def oursql_conn():
import oursql
conn = oursql.connect(
host=config.HOST, user=config.USER, passwd=config.PASS,
db=config.MYDB)
return conn
def mysqldb_conn():
conn = MySQLdb.connect(
host=config.HOST, user=config.USER,
passwd=config.PASS, db=config.MYDB,
cursorclass=cursors.SSCursor)
return conn
def two_cursors_one_conn():
"""Two SSCursors can not use one connection concurrently"""
def worker(conn):
cursor = conn.cursor()
cursor.execute(query)
for row in cursor:
logger.info(row)
conn = mysqldb_conn()
threads = [threading.Thread(target=worker, args=(conn,))
for n in range(2)]
for t in threads:
t.daemon = True
t.start()
# Second thread may hang or raise OperationalError:
# File "/usr/lib/pymodules/python2.7/MySQLdb/cursors.py", line 289, in _fetch_row
# return self._result.fetch_row(size, self._fetch_type)
# OperationalError: (2013, 'Lost connection to MySQL server during query')
for t in threads:
t.join()
def two_cursors_two_conn():
"""Two SSCursors from independent connections can use the same table concurrently"""
def worker():
conn = mysqldb_conn()
cursor = conn.cursor()
cursor.execute(query)
for row in cursor:
logger.info(row)
threads = [threading.Thread(target=worker) for n in range(2)]
for t in threads:
t.daemon = True
t.start()
for t in threads:
t.join()
logging.basicConfig(level=logging.DEBUG,
format='[%(asctime)s %(threadName)s] %(message)s',
datefmt='%H:%M:%S')
two_cursors_one_conn()
two_cursors_two_conn()
Not:
İşte sorunu gösteren bazı kodudur. oursql imleçleri, fetch rows lazily by default olan gerçek sunucu tarafı imleçlerdir. oursql
yüklü ile, asılı ya da bir istisna yükseltmeden
conn = mysqldb_conn()
için
conn = oursql_conn()
sonra two_cursors_one_conn()
çalışır değiştirirseniz.
Bu, bellek sorunlarımı MySQL ve yield_per ile çözdü. Trac’in cevabının niçin "işe yaramamış" olduğuna dair bir fikri var mı? – bcoughlan
@bcoughlan: Bazı kodları ekledim ve aynı anda SSCursors kullanmanın sınırlamalarını tartıştım. – unutbu
Bu mysqldb için çözülmelidir, mysqlconnector için benzer bir seçenek var, bu sürücüyü kullanarak benzer bir sorunla karşılaşıyorum. –