2010-09-23 11 views
5

Viene visualizzato un errore davvero strano, inutile e totalmente casuale quando recupero le righe da una risorsa (query) utilizzando PHP.Errore MySQL "Empty rowet body body" quando si utilizza mysql_fetch_object (PHP 5.3.3)

La mia macchina di sviluppo è un Windows XP SP3 con Apache 2.2 mentre MySQL gira su una macchina virtuale, usando ubuntu 10.04, con 768mb di ram, 100GB di HDD e 4 core logici (Intel q6600). Tuttavia questo problema non è legato a PHP su Windows perché ottengo lo stesso errore quando eseguo il codice sulla macchina del database.

sto usando mysql estensione (non mysqli o mysqlnd), ma guardando in giro ho fondato una patch quanto riguarda questo errore relative al mysqlnd estensione, quindi, probabilmente, dovrei provare.

Il problema principale è che quando eseguo questa query (una query molto grande con un paio di tabelle derivate e più di 20 join) e il risultato dei processi è veloce e tutto va bene, ma quando il mio codice è stato di circa 15/20 secondi per elaborare un blocco di righe (ho bisogno di costruire un oggetto da un blocco di righe collegate in un modo molto particolare tra di loro, non posso cambiarlo, il database non è mio e fare un po 'di PDF da questo oggetto) dopo un po' (tempo casuale) Ottengo questo errore "Empty packet body body".

Uso query senza buffer per ridurre il consumo di memoria (se abilito il buffering ottengo circa 260 MB di memoria utilizzata) ma questo non dovrebbe essere il problema.

+0

Puoi mostrare un po 'di codice? A cosa servono i timeout dei comandi? – Fosco

+0

il problema non è correlato a timeout o limite di memoria perché ho disabilitato il primo e impostato su un valore molto molto alto il secondo –

+0

Dove lavoro sviluppiamo usando un Apache 2.2/PHP 5.3.3 locale su Windows XP Anche Pro SP3 e un server di database di test condiviso, e riceviamo questo errore tutto il tempo. TUTTAVIA, l'installazione Apache/Linux condivisa, di cui non sono a conoscenza le versioni, non fornisce questo errore, quindi questo potrebbe suggerire che il problema potrebbe essere causato dalla versione di Apache o qualcosa di simile invece della configurazione o dell'uso del database! –

risposta

16

Ho avuto lo stesso errore. Stavo usando PDO, ma dovrebbe essere fondamentalmente la stessa cosa.

State operando su un tavolo MyISAM? In tal caso, il problema è probabilmente correlato al modello di blocco utilizzato da Engine: blocca l'intera tabella, per la lettura con un blocco condiviso, per la scrittura con un blocco esclusivo.

Questo è ciò che stavo cercando di fare: leggere un grande set di risultati senza buffer e aggiornare alcune delle righe nella stessa tabella. Poiché non è possibile emettere un'istruzione sulla stessa connessione mentre contiene un set di risultati senza buffer, ho provato a utilizzare un'altra connessione per gli aggiornamenti. La lettura è andata bene fino al primo aggiornamento, a quel punto la sceneggiatura si è bloccata per circa un minuto, poi ho ricevuto l'errore "Corpo riga pacchetto vuoto".

Si vede, durante la lettura senza buffer, il blocco condiviso viene mantenuto fino a quando l'intero set di risultati è stato letto o il cursore viene chiuso. Durante questo periodo, la tabella viene bloccata con un blocco condiviso, quindi altre connessioni possono ottenere blocchi condivisi sul tavolo (in altre parole, letti da esso), ma i blocchi esclusivi (per la scrittura) dovranno attendere. Se questo accade all'interno dello stesso script, si bloccherà.

Ora, per prevenire un deadlock infinito, MySQL rilascia forzatamente il blocco condiviso dopo un po '(IIRC è influenzato dal valore di table_lock_wait_timeout), scarica il set di risultati e consente all'istruzione di scrittura con il blocco esclusivo in attesa di ottenere il suo girare.

Quindi, mentre nel mio caso era lo stesso script che faceva questo e quindi si fermava fino al termine del timeout, potrebbe anche essere che qualche altro script stia tentando un'operazione di scrittura sul tavolo con lo stesso effetto, che è probabilmente cosa è successo nel tuo caso.

Ciò che ha risolto il problema per me è stato modificare il tipo di tabella in InnoDB, poiché tale motore utilizza i blocchi a livello di riga anziché a livello di tabella. Tuttavia, dal momento che dici che il database non è tuo, questo potrebbe non essere possibile per te.

+0

Inizialmente il tipo di tabella era myisam, successivamente sono passato a innodb per fare un test ma il problema è rimasto. Tuttavia in realtà non l'ho più capito, devo stressare il server per ottenerlo –

+0

Esattamente il mio problema! Ottima risposta, grazie. – mpen

+0

Questo non ha funzionato per me, anche quando il tavolo è stato copiato e sono sicuro al 100% che nessuno ci abbia scritto. – Chris

0

La risposta dell'utente589182 è azzeccata. Sto facendo essenzialmente la stessa cosa: leggi un grande set di risultati senza buffer e aggiorna alcune delle righe nella stessa tabella, dallo stesso script PHP. Ho avuto esattamente lo stesso messaggio di errore dopo ca. 2500 AGGIORNAMENTI.Problema risolto dopo il passaggio da MyISAM a InnoDB.

+0

beh, sono su innodb ma se i hyper-stress mysql, ottengo l'errore. –

0

Ho ricevuto lo stesso errore e stavo anche leggendo un grande set di risultati senza buffer durante l'aggiornamento delle righe della stessa tabella.

Invece di passare a InnoDB, una soluzione migliore potrebbe essere quella di creare una tabella temporanea contenente solo la chiave primaria della tabella originale. Quindi, passa attraverso quella tabella temporanea mentre selezioni e aggiorni una riga alla volta dalla tabella originale. Dovrai utilizzare due connessioni MySQL separate per fare ciò, altrimenti otterrai un errore "Comandi non sincronizzati".

Potrebbe essere necessario bloccare la tabella originale per impedire a chiunque altro di leggere/scrivere mentre ciò accade.

0

Ero su InnoDB e non ho mai avuto questo tipo di problema finché non ho cambiato ambiente di codifica (letteralmente, come la posizione). Quindi, se hai cambiato la tua connessione wireless, questo potrebbe essere il problema soprattutto se è un luogo pubblico.

1

Dopo questo errore un po 'un fa, ho fissato che aumentando il valore di

net_read_timeout = 360 
net_write_timeout = 360 

Mentre una connessione è aperta su di scrittura, in attesa di un'altra query alla fine di continuare l'inserimento, questa volte su , dando un pacchetto di righe vuoto. Sto lavorando su un set di dati molto grande, il valore utilizzato è oltre 360. Il tuo valore dipenderà dal tuo caso d'uso.