2010-09-23 17 views
5

Obtengo un error realmente extraño, inútil y totalmente aleatorio cuando obtengo filas de un recurso (consulta) usando PHP.Extraño error de MySQL "Empty row packet body" cuando se usa mysql_fetch_object (PHP 5.3.3)

Mi máquina de desarrollo es un Windows XP SP3 con Apache 2.2 mientras que MySQL se ejecuta en una máquina virtual, usando ubuntu 10.04, con 768mb de ram, 100GB de HDD y 4 núcleos lógicos (Intel q6600). Sin embargo, este problema no está relacionado con PHP en Windows porque obtengo el mismo error cuando ejecuto el código en la máquina de la base de datos.

estoy usando mysql extensión (no mysqli o mysqlnd), pero mirando a su alrededor fundé un parche con respecto a este error relacionado con mysqlnd extensión, por lo que, probablemente, debería intentarlo.

El problema principal es que cuando ejecuto esta consulta (una consulta realmente grande con un par de tablas derivadas y más de 20 uniones) y proceso los resultados rápidamente y todo va bien, pero cuando mi código gastó alrededor de 15/20 segundos para procesar un bloque de filas (necesito construir un objeto a partir de un bloque de filas vinculadas de una manera muy particular entre ellos, no puedo cambiar esto, la base de datos no es mía, y hacer un PDF de este objeto) después de un tiempo (tiempo aleatorio) Recibo este error "Empty row packet body".

Uso las consultas sin búfer para reducir el consumo de memoria (si habilito el almacenamiento en búfer recibo alrededor de 260MB de memoria usada) pero este no debería ser el problema.

+0

¿Puedes mostrar algún código? ¿Cuáles son tus tiempos de espera de comando establecidos? – Fosco

+0

el problema no está relacionado con los tiempos de espera o el límite de memoria porque he desactivado el primero y configuré un valor muy muy alto el segundo –

+0

Donde trabajo desarrollamos usando un Apache 2.2/PHP 5.3.3 local en un Windows XP Pro SP3 también, y un servidor de base de datos de prueba compartida, y obtenemos este error todo el tiempo. SIN EMBARGO, la configuración compartida de Apache/Linux, cuyas versiones no conozco, no da este error, por lo que esto podría sugerir que el problema podría ser causado por la versión de Apache o algo así en lugar de la configuración de la base de datos o el uso. –

Respuesta

16

Me encontré con el mismo error. Estaba usando PDO, pero básicamente debería ser lo mismo.

¿Está trabajando en una tabla MyISAM? Si es así, el problema probablemente esté relacionado con el modelo de bloqueo que utiliza este motor: bloquea toda la tabla, para leer con un candado compartido, para escribir con un candado exclusivo.

Esto es lo que estaba tratando de hacer: leer un gran conjunto de resultados sin búfer, y actualizar algunas de las filas en la misma tabla. Como no puede emitir una declaración en la misma conexión mientras contiene un conjunto de resultados sin búfer, traté de usar otra conexión para las actualizaciones. La lectura fue bien hasta la primera actualización, momento en el que la secuencia de comandos se detuvo durante aproximadamente un minuto, luego recibí el error "Vaciar el cuerpo del paquete de filas".

Como ve, al leer sin búfer, el bloqueo compartido se mantiene hasta que se lea el conjunto de resultados completo o se cierre el cursor. Durante ese tiempo, la tabla se bloquea con un bloqueo compartido, por lo que otras conexiones pueden obtener bloqueos compartidos en la tabla (en otras palabras, leer de ella), pero los bloqueos exclusivos (para escritura) tendrán que esperar. Si esto ocurre dentro del mismo script, se estancará.

Ahora, para evitar interbloqueo interminable, MySQL liberará forzosamente su bloqueo compartido después de un tiempo (IIRC esto se ve afectado por el valor de table_lock_wait_timeout), volcando su conjunto de resultados y permitiendo que la instrucción de escritura con el bloqueo exclusivo en espera obtenga su giro.

Así que, aunque en mi caso era el mismo script el que hacía esto y por lo tanto se detenía hasta que expiraba el tiempo de espera, también podría ser que algún otro script intente una operación de escritura con el mismo efecto, que probablemente qué pasó en tu caso

Lo que me solucionó el problema fue cambiar el tipo de tabla a InnoDB, ya que ese motor usa bloqueos de nivel de fila en lugar de bloqueos de nivel de tabla. Sin embargo, como dice que la base de datos no es suya, puede que esto no sea posible para usted.

+0

Inicialmente el tipo de tabla era myisam, luego cambié a innodb para hacer una prueba pero el problema persistía. Sin embargo, en realidad ya no lo conseguí, debo insistir mucho en el servidor para obtenerlo –

+0

¡Exactamente mi problema! Gran respuesta, gracias. – mpen

+0

Esto no funcionó para mí, incluso cuando se copió la tabla y estoy 100% seguro de que nadie estaba escribiendo en ella. – Chris

0

user589182 la respuesta es perfecta. Estoy haciendo básicamente lo mismo: leer un gran conjunto de resultados sin búfer y actualizar algunas de las filas en la misma tabla, desde el mismo script PHP. Recibí exactamente el mismo mensaje de error después de aprox. 2500 ACTUALIZACIONES.Problema resuelto después de cambiar de MyISAM a InnoDB.

+0

bueno, estoy en innodb pero si hiper-estrés mysql, me sale el error. –

0

Recibí el mismo error, y también estaba leyendo un gran conjunto de resultados sin búfer mientras actualizaba las filas de la misma tabla.

En lugar de cambiar a InnoDB, una mejor solución podría ser crear una tabla temporal que contenga solo la clave principal de la tabla original. Luego, recorra esa tabla temporal mientras selecciona y actualiza una fila a la vez desde la tabla original. Deberá usar dos conexiones MySQL separadas para hacer esto, de lo contrario obtendrá un error de "Comandos desincronizados".

Es posible que tenga que bloquear la tabla original para evitar que otra persona lea o escriba en ella mientras esto sucede.

0

Estaba en InnoDB y nunca tuve este tipo de problema hasta que cambie el entorno de codificación (literalmente, como la ubicación). Entonces, si cambió su conexión inalámbrica, ese puede ser el problema, especialmente si es un lugar público.

1

Tras este error cuando una hace, lo he arreglado, aumentando el valor de

net_read_timeout = 360 
net_write_timeout = 360 

Mientras que una conexión está abierta en la escritura, a la espera de otra consulta para poner fin a continuar insertando, este tiempo de espera , dando un paquete de fila vacía. Estoy trabajando en un conjunto de datos muy grande, el valor utilizado es más de 360. Su valor dependerá de su caso de uso.

Cuestiones relacionadas