2009-12-10 15 views
41

Ho una tabella enorme e ho bisogno di elaborare tutte le righe al suo interno. Ricevo sempre questo messaggio di connessione persa e non riesco a ricollegarmi e ripristinare il cursore nell'ultima posizione in cui si trovava. Questo è fondamentalmente il codice che ho qui:Connessione persa al server MySQL durante la query

# 
import MySQLdb 

class DB: 
    conn = None 

    def connect(self): 
    self.conn = MySQLdb.connect('hostname', 'user', '*****', 'some_table', cursorclass=MySQLdb.cursors.SSCursor) 

    def query(self, sql): 
    try: 
    cursor = self.conn.cursor() 
    cursor.execute(sql) 
    except (AttributeError, MySQLdb.OperationalError): 
    self.connect() 
    cursor = self.conn.cursor() 
    cursor.execute(sql) 
    return cursor 
# 

# 
db = DB() 
sql = "SELECT bla FROM foo" 
data = db.query(sql) 

for row in data: 
    do_something(row) 
# 

Ma sto ottenendo sempre questo:

# 
Traceback (most recent call last): 
    File "teste.py", line 124, in <module> 
    run() 
File "teste.py", line 109, in run 
    for row in data: 
File "/usr/lib64/python2.5/site-packages/MySQLdb/cursors.py", line 417, in next 
    row = self.fetchone() 
File "/usr/lib64/python2.5/site-packages/MySQLdb/cursors.py", line 388, in fetchone 
    r = self._fetch_row(1) 
File "/usr/lib64/python2.5/site-packages/MySQLdb/cursors.py", line 285, in _fetch_row 
    return self._result.fetch_row(size, self._fetch_type) 
    _mysql_exceptions.OperationalError: (2013, 'Lost connection to MySQL server during query') 
    Exception _mysql_exceptions.OperationalError: (2013, 'Lost connection to MySQL server during query') in <bound method SSCursor.__del__ of <MySQLdb.cursors.SSCursor object at 0x7f7e3c8da410>> ignored 
# 

Avete qualche idea?

+0

La rimozione di "cursorclass = MySQLdb.cursors.SSCursor" dalla chiamata connect() è sufficiente. Funziona abbastanza bene ora. Grazie. – Otavio

+0

Ho avuto lo stesso problema, ma ho ~ 1B di file di dati, quindi voglio usare SSCursor per memorizzare nella cache dati interrogati sul lato mysqld invece della mia applicazione python. allargata net_write_timeout per 1 ora risolto il problema :) – cow

risposta

8

È necessario aumentare il timeout sulla connessione. Se non si può o non si vuole fare che per qualche ragione, si potrebbe provare a chiamare:

data = db.query(sql).store_result() 

Verrà recuperato tutti i risultati subito, quindi la tua connessione non saranno timeout a metà strada attraverso l'iterazione su di loro .

+0

di rinvio e una soluzione permanente [documentazione MySQL] (https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_connect_timeout) –

+0

controlla anche [stackoverflow] (https://stackoverflow.com/a/644745/1085495) –

35

La documentazione di MySQL hanno una pagina intera dedicata a questo errore: http://dev.mysql.com/doc/refman/5.0/en/gone-away.html

di nota sono

  • È inoltre possibile ottenere questi errori se si invia una query al server che non è corretto o troppo grande. Se mysqld riceve un pacchetto troppo grande o fuori servizio, presuppone che qualcosa sia andato storto con il client e chiuda la connessione. Se hai bisogno di grandi queries (ad esempio, se stai lavorando con grandi colonne BLOB), puoi aumentare il limite della query impostando la variabile max_allowed_packet del server, che ha un valore predefinito di 1 MB. Potrebbe anche essere necessario aumentare la dimensione massima del pacchetto sul lato client. Ulteriori informazioni sull'impostazione della dimensione del pacchetto sono fornite nella Sezione B.5.2.10, "Pacchetto troppo grande".

  • È possibile ottenere ulteriori informazioni sulle connessioni perse avviando mysqld con l'opzione --log-warnings = 2. Questo registra alcuni degli errori disconnessi nel file hostname.err

+0

Un altro motivo potrebbe essere che mysqld si blocca. – automatthias

11

Assicurarsi di chiudere il cursore prima della connessione. Ho risolto il mio problema con questo:

if cur and con:       
    cur.close() 
    con.close() 
3

Impostare l'impostazione 'max_allowed_packet' su 64M e riavviare il server MySql. Se ciò non risolvesse i tuoi problemi, il problema potrebbe risiedere altrove.

Ho un'applicazione CLI PHP multi-thread che esegue query simultanee e di recente ho notato questo problema. Ora è ovvio per me che il server MySql considera tutte le connessioni dallo stesso IP come una connessione "singola" e quindi rilascia tutte le connessioni ogni volta che una singola query termina.

Mi chiedo però che ci sia un modo per consentire a MySql di consentire 100 connessioni dallo stesso IP e considerare ogni connessione come una singola connessione.

+2

Non penso che la tua affermazione su "tutte le connessioni dallo stesso IP di una connessione" sing "sia corretta. Potresti vederlo perché i metodi mysql potrebbero riutilizzare una connessione persistente tra i tuoi "thread" PHP. – pawstrong

12

Ci sono tre modi per ingrandire l'max_allowed_packet di server MySQL:

  1. Variazione max_allowed_packet=64M nel file di /etc/mysql/my.cnf sulla macchina server MySQL e riavviare il server
  2. Eseguire lo sql sul server MySQL: set global max_allowed_packet=67108864;
  3. Python esegue SQL dopo la connessione alla mysql:

connection.execute('set max_allowed_packet=67108864')

6

You can also encounter this error with applications that fork child processes, all of which try to use the same connection to the MySQL server. This can be avoided by using a separate connection for each child process.

Le forcelle potrebbero colpirti. Attenzione però non in questo caso.

1

questo stava accadendo a me con MariaDB perché ho fatto una colonna di varchar(255) un unique key .. Direi che è troppo pesante per un unico, come l'inserto è stato timeout.

5

ho il mio caso il motivo dell'errore

ERROR 2013 (HY000): Lost connection to MySQL server during query

era che le parti del mio tavolo erano corrotto. Non ero inoltre in grado di effettuare il mysqldump tabella perché alcune righe l'hanno interrotta. L'errore non era correlato a problemi di memoria ecc. Come menzionato sopra.

La cosa bella è che MySQL mi ha restituito il numero di riga che è stato il primo a fallire. E 'stato qualcosa di simile

mysqldump: Error 2013: Lost connection to MySQL server during query when dumping table mytable at row: 12723

La soluzione era quella di copiare i dati in una nuova tabella. Nel mio caso ho perso 10 righe di dati perché ho dovuto saltare queste righe danneggiate. Per prima cosa ho creato una tabella "tmp" con lo schema di quello vecchio. SHOW CREATE TABLE è tuo amico qui. Per esempio.

SHOW CREATE TABLE mydatabase.mytable; 

Con l'ho creato il nuovo tavolo. Chiamiamolo mytabletmp. E quindi copia le righe che sei in grado di copiare, ad es.

insert into mysqltabletmp select * from mytable where id < 12723; 
insert into mysqltabletmp select * from mytable where id > 12733; 

Dopo tale eliminazione della vecchia tabella, rinominare la tabella tmp con il nome della tabella precedente.

Ci sono anche some nice Information from Peter per questo problema.

1

Questo può accadere anche se qualcuno o qualcosa uccide la connessione utilizzando lo KILL command.

1

Questo è successo a me quando ho tentato di aggiornare una tabella la cui dimensione su disco era maggiore dello spazio disponibile su disco. La soluzione per me era semplicemente aumentare lo spazio disponibile su disco.

0

Nel mio caso, ho riscontrato questo problema durante l'acquisizione di un dump SQL che aveva posizionato le tabelle nell'ordine errato. Il CREATE in questione includeva un CONSTRAINT ... REFERENCES che faceva riferimento a una tabella che non era ancora stata creata.

Ho localizzato la tabella in questione e ho spostato la sua istruzione CREATE su quella precedente e l'errore è scomparso.

L'altro errore che ho riscontrato relativo a questo dump difettoso era ERROR 1005/errno: 150 - "Impossibile creare la tabella", di nuovo una questione di tabelle create senza ordine.

0

Questo è successo a me quando il mio nome CONSTRAINT ha lo stesso nome con altro nome CONSTRAINT.

Modifica il mio nome CONSTRAINT risolto.

1

Ho riscontrato anche problemi simili. Nel mio caso è stato risolto da ottenere il cursore in questo modo:

cursor = self.conn.cursor(buffered=True) 
+0

Stavo usando mysql.connector invece di MySQLdb – user6938211

0

Multiprocessing e Django DB non giocare bene insieme.

Ho finito per chiudere la connessione Django DB per prima cosa nel nuovo processo.

In modo che uno non avrà riferimenti alla connessione utilizzata dal genitore.

from multiprocessing import Pool 

multi_core_arg = [[1,2,3], [4,5,6], [7,8,9]] 
n_cpu = 4 
pool = Pool(n_cpu) 
pool.map(_etl_, multi_core_arg) 
pool.close() 
pool.join() 

def _etl_(x): 
    from django.db import connection 
    connection.close() 
    print(x) 

O

Process.start() chiama una funzione che inizia con

Alcuni altri suggeriscono di utilizzare

from multiprocessing.dummy import Pool as ThreadPool 

risolto il mio (2013, Connessione persa) problema, ma l'uso filo GIL , quando faccio IO, lo rilascerà quando IO termina.

Comparativamente, Processo genera un gruppo di lavoratori che si comunicano tra loro, il che può essere più lento.

Vi consiglio di cronometrare. Un consiglio laterale è quello di utilizzare joblib che è supportato dal progetto scikit-learn. alcuni risultati delle prestazioni mostrano che esegue il pool nativo() .. anche se lascia la responsabilità al codificatore per verificare il costo di esecuzione vero.

0

Ho incontrato lo stesso problema. A causa di altri problemi, avevo provato ad aggiungere una linea cnx.close() alle altre mie funzioni. Invece, ho rimosso tutte queste chiude estranei e messa a punto la mia classe in questo modo:

class DBase: 

config = { 
     'user': 'root', 
     'password': '', 
     'host': '127.0.0.1', 
     'database': 'bio', 
     'raise_on_warnings': True, 
     'use_pure': False, 
     } 

def __init__(self): 
    import mysql.connector 
    self.cnx = mysql.connector.connect(**self.config) 
    self.cur = self.cnx.cursor(buffered=True) 
    print(self.cnx) 
def __enter__(self): 
    return DBase() 

def __exit__(self, exc_type, exc_val, exc_tb): 
    self.cnx.commit() 
    if self.cnx: 
     self.cnx.close() 

qualsiasi funzione che è chiamato all'interno di questa classe è collega, si impegna, e si chiude.

Problemi correlati