2009-12-10 31 views
41

Tengo una gran tabla y necesito procesar todas las filas en ella. Siempre recibo este mensaje de conexión perdida y no puedo volver a conectar y restaurar el cursor a la última posición que tenía. Este es básicamente el código que tengo aquí:Conexión perdida al servidor MySQL durante la consulta

# 
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) 
# 

Pero siempre estoy haciendo esto:

# 
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 
# 

¿Tiene alguna idea?

+0

Eliminar "cursorclass = MySQLdb.cursors.SSCursor" de la llamada de connect() es suficiente. Está funcionando bastante bien ahora. Gracias. – Otavio

+0

tuve el mismo problema, pero tengo ~ 1B filas de datos, así que quiero usar SSCursor para almacenar en caché los datos consultados en el lado de mysqld en lugar de en mi aplicación de Python. net_write_timeout ampliada a 1 hora fija la cuestión :) – cow

Respuesta

8

Necesita aumentar el tiempo de espera de su conexión. Si usted no puede o no quiere hacer eso por alguna razón, usted podría intentar llamar:

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

Esto obtendrá todos los resultados inmediatamente, a continuación, la conexión se tiene tiempo de espera medio camino a través de la iteración sobre ellos .

+0

para referencia y una solución permanente [docs MySQL] (https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_connect_timeout) –

+0

también compruebe [stackoverflow] (https://stackoverflow.com/a/6447452/1085495) –

35

Los documentos MySQL no tienen una página entera dedicada a este error: http://dev.mysql.com/doc/refman/5.0/en/gone-away.html

de la nota son

  • También puede obtener estos errores si envía una consulta al servidor que es incorrecta o demasiado grande. Si mysqld recibe un paquete que es demasiado grande o está fuera de servicio, asume que algo ha ido mal con el cliente y cierra la conexión. Si necesita grandes consultas (por ejemplo, si está trabajando con grandes columnas BLOB), puede aumentar el límite de consultas configurando la variable max_allowed_packet del servidor, que tiene un valor predeterminado de 1 MB. Es posible que también necesite aumentar el tamaño máximo de paquete en el extremo del cliente. Se proporciona más información sobre cómo configurar el tamaño del paquete en la Sección B.5.2.10, "Paquete demasiado grande".

  • Puede obtener más información sobre las conexiones perdidas iniciando mysqld con la opción --log-warnings = 2. Esto registra algunos de los errores desconectados en el archivo hostname.err

+0

Otra razón podría ser que mysqld está fallando. – automatthias

11

Asegúrese de cerrar el cursor antes de la conexión. He resuelto mi problema con esto:

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

Establecer el 'max_allowed_packet' establecer a 64M y reinicie el servidor MySQL. Si eso no solucionó sus problemas, el problema puede estar en otra parte.

Tengo una aplicación de CLI PHP multiproceso que realiza consultas simultáneas y recientemente me di cuenta de este problema. Ahora es obvio para mí que el servidor MySql considera todas las conexiones desde la misma IP como una conexión 'única' y, por lo tanto, descarta todas las conexiones cada vez que finaliza una única consulta.

Me pregunto sin embargo que hay una manera de hacer que MySql permita decir 100 conexiones desde la misma IP y considere cada conexión como una conexión individual.

+2

No creo que su afirmación sobre "todas las conexiones desde la misma IP como una conexión 'sing'e' sea correcta. Puede estar viendo eso porque los métodos mysql pueden estar reutilizando una conexión persistente entre sus "hilos" de PHP. – pawstrong

12

Hay tres maneras de ampliar el max_allowed_packet del servidor MySQL:

  1. Cambio max_allowed_packet=64M en el archivo /etc/mysql/my.cnf en la máquina servidor MySQL y reiniciar el servidor
  2. Ejecutar el SQL en el servidor MySQL: set global max_allowed_packet=67108864;
  3. Python ejecuta sql después de conectarse a la 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.

Las horquillas te pueden pegar. Sin embargo, ten cuidado no en este caso.

1

esto sucedía a mí con MariaDB porque hice una columna varchar(255) un unique key .. supongo que es demasiado pesado para un único, como el inserto fue el tiempo de espera.

5

que mi caso el motivo del error

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

fue que partes de mi mesa estaban corrompidos . Tampoco pude mysqldump mi tabla porque algunas filas la rompieron. El error no estaba relacionado con ningún problema de memoria, etc., como se mencionó anteriormente.

Lo bueno fue que MySQL me devolvió el número de fila, que fue el primero que falló. Fue algo así como

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

La solución fue copiar los datos en una nueva tabla. En mi caso, perdí 10 filas de datos porque tuve que omitir estas filas dañadas. Primero creé una tabla "tmp" con el esquema del anterior. SHOW CREATE TABLE es tu amigo aquí. P.ej.

SHOW CREATE TABLE mydatabase.mytable; 

Con la he creado la nueva tabla. Llamémoslo mytabletmp. Y luego copie las filas que puede copiar, p. Ej.

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

Después de que la caída de la mesa de edad, cambiar el nombre de TMP-mesa para el viejo nombre de la tabla.

También hay some nice Information from Peter con respecto a este problema.

1

Esto también puede ocurrir si alguien o algo mata su conexión usando el KILL command.

1

Esto me sucedió cuando traté de actualizar una tabla cuyo tamaño en el disco era más grande que el espacio disponible en el disco. La solución para mí fue simplemente aumentar el espacio disponible en el disco.

0

En mi caso, me encontré con este problema al obtener un volcado de SQL que había colocado las tablas en el orden incorrecto. El CREATE en cuestión incluía una RESTRICCIÓN ... REFERENCIAS que hacía referencia a una tabla que aún no se había creado.

Localicé la tabla en cuestión, y moví su declaración CREATE al estado anterior y el error desapareció.

El otro error que encontré relacionado con este volcado defectuoso fue ERROR 1005/errno: 150 - "No se puede crear la tabla", una vez más una cuestión de tablas que se están creando fuera de servicio.

0

Esto me pasó cuando mi nombre CONSTRAINT tiene el mismo nombre con otro nombre CONSTRAINT.

Al cambiar mi nombre CONSTRAINT se solucionó esto.

1

También encontré problemas similares. En mi caso fue resuelto por conseguir el cursor de esta manera:

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

Estaba usando mysql.connector en lugar de MySQLdb – user6938211

0

multiprocesamiento y Django DB no juegan bien juntos.

Terminé cerrando la conexión Django DB a primera vista en el nuevo proceso.

Para que uno no tenga referencias a la conexión utilizada por el padre.

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() llama a una función que se inicia con

Algunos otros sugieren utilizar

from multiprocessing.dummy import Pool as ThreadPool 

Se resolvió mi (2013, perdió la conexión) problema, pero el uso de hilo GIL , al hacer IO, lo liberará cuando termine IO.

Comparativamente, el proceso genera un grupo de trabajadores que se comunican entre sí, lo que puede ser más lento.

Te recomiendo que lo cronometras. A consejos generales es usar joblib que está respaldado por el proyecto scikit-learn. algunos resultados de rendimiento muestran que realiza el Pool nativo() .. aunque deja la responsabilidad al codificador para verificar el verdadero costo del tiempo de ejecución.

0

Me encontré con el mismo problema. Debido a algunos otros problemas, intenté agregar una línea cnx.close() a mis otras funciones. En su lugar, quité todos estos extraños se cierra y la configuración de mi clase como esta:

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() 

cualquier función que se llama dentro de esta clase es conecta, se compromete, y se cierra.

Cuestiones relacionadas