2013-01-08 11 views
9

Ho una query di aggiornamento mySQL che a volte aggiornerà tutti i campi e talvolta aggiornerà tutti i campi tranne uno.a volte non aggiorna il campo nel database mySQL

Non funziona su circa il 10% delle chiamate.

Il mio tavolo è:

CREATE TABLE IF NOT EXISTS `grades` ( 
`id` int(11) NOT NULL AUTO_INCREMENT, 
`state` int(1) NOT NULL, 
`result` varchar(255) NOT NULL, 
`date_synced` datetime NOT NULL, 
`updated_at` datetime NOT NULL, 
PRIMARY KEY (`id`)) 
ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=4395 ; 

La mia domanda è:

$sqlstr = "UPDATE grades SET result = '$result', state = 2, date_synced = '$date', updated_at = '$date' WHERE id = $id"; 

Quando non riesce, di conseguenza, date_synced, e updated_at vengono aggiornati, ma lo stato rimane invariato.

C'è un'altra query che aggiorna solo il campo di stato e quello anche in modo intermittente non riesce.

Non sono stato in grado di ricreare il problema nel nostro ambiente di test. Potrebbe esserci qualcosa di sbagliato nel database mySQL di produzione o in qualche tipo di collisione bloccante?


Ho ulteriori informazioni. Sto usando mysqli. L'altra query che aggiorna solo lo stato sta usando mysql. Ciò causerebbe un problema?

Pensavo che InnoDB fosse bloccato per riga. Non consente gli aggiornamenti di riga parziale, vero?


Un altro aggiornamento per indirizzare i commenti.

Il mio flusso di codice è piuttosto lineare.

The row is created with state=0. 
<flash stuff here> and the row is updated with state=1 
A cron job pulls all state=1 and sends an api call 
if api call is successful, the row is updated with state=2, result, date_synced, and updated_at 
if api call is error, the row is updated with state=3, result, and updated_at 

Il campo è stato mai messo di nuovo a 0 (dopo il flash) o 1 (dopo la chiamata API). Poiché la data _sincronizzato e il risultato sono stati impostati ma (a volte) lo stato è ancora 1, è come se l'aggiornamento al campo dello stato venisse eliminato.

Aggiungo il trigger di aggiornamento e vedo se questo mi dà più informazioni.

+3

è necessario aggiungere un trigger di aggiornamento e una tabella di registro che memorizzi i vecchi e nuovi valori insieme a id, id di sessione e utente corrente per il debug. forse le modifiche passano ma sono state sovrascritte da un'altra affermazione –

+1

Penso che il commento di Sir Rufo potrebbe essere super-utile per la tua situazione, perché aiuterà a definire la sequenza in cui accadono le cose e se si tratta di uno scenario più complesso in cui compaiono più query nella foto che stai vedendo. – DWright

+1

"[..] o una sorta di collisione di blocco [..]" poiché altri campi della stessa riga sono stati aggiornati, non si verificano problemi di blocco. la cosa più piccola che innodb può bloccare è una riga. non riesco a bloccare un singolo campo – scones

risposta

1

Si afferma che "{n} Righe interessate?"

Inoltre, è ripetibile; puoi eseguire la stessa query sugli stessi dati esatti e farà cose diverse?

In tal caso, è possibile che si disponga di un'installazione danneggiata o di un database danneggiato.

Hai provato a fare una riparazione & ottimizzare sui tavoli? Questo potrebbe aiutare.

Mi dispiace per la risposta pallettoni: P

0

riaggiustare il vostro "severità" in MySQL per TRADIZIONALE:

SET sql_mode = 'TRADITIONAL'; 

e provare l'inserto dal console senza PHP. Quindi controlla gli errori che potrebbero spiegarlo.

Ripristinare il rigore a "perdonare" da:

SET sql_mode = ''; 

Oppure, se si sta utilizzando un oggetto PDO per la connessione al database di un errore indietro attraverso PHP con qualcosa di simile:

try { 
    $sqlstr = "UPDATE grades SET result = '$result', state = 2, date_synced = '$date',updated_at = '$date' WHERE id = $id"; 
$s = $pdo->exec($sqlstr); 
} 
catch (PDOException $e) { 
    $error = $e->getMessage(); 
    echo $error; 
} 

Fondamentalmente, fai tutto il necessario per ottenere il messaggio di errore su cosa sta succedendo. È probabile che SQL stia inviando un errore, ma PHP non è impostato per mostrarlo nel tuo script.

+0

In realtà, è probabile che MySQL stia generando un avviso perché INT (1) è stato troncato o qualcosa del genere. Quindi PHP potrebbe semplicemente ignorare l'avviso e continuare. –

+1

FWIW, INT (1) e INT (1000000) sono esattamente gli stessi per la memorizzazione e l'intervallo di valori supportati. L'argomento non è un limite di lunghezza, è un suggerimento di visualizzazione. INT di MySQL è sempre un tipo di dati a 32 bit. –

0

Prova a cambiare il nome del campo da 'stato' a qualcos'altro, come 'stato_num'. Anche se non è elencato come parola di riserva per MySQL, il nome potrebbe causare problemi.

0

La query che imposta "stato" e altri campi viene eseguita due volte ea volte una delle attività viene completata più rapidamente di un'altra. Aggiorna tutti i campi e lo script che ha chiamato quell'attività esegue anche la query MySQL che aggiorna il campo "stato".

Ad esempio, si dispone di uno script PHP che esegue un comando di shell "tar" in background tramite exec() e imposta "stato" in DB dopo il completamento. La prossima stringa del codice PHP aggiorna il tuo "stato" nel tuo database. Ma a volte il comando bash che hai chiamato viene eseguito più velocemente dello script PHP che chiama l'aggiornamento MySQL (se questo comando bash viene eseguito in background).

Primo passo: eseguire script bash da PHP che fissano "stato" = 3 (aspetta l'ulteriore elaborazione) dopo la completa, aggiornare altri campi con la data, ecc

passo successivo: in PHP dopo exec() si imposta "stato" = 2 (in corso). In questo caso se il tuo script bash in background farà il lavoro più velocemente di PHP esegue query di aggiornamento MySQL, riceverai il valore aggiornato della data e anche "stato" = 2 (ma aveva valore = 3 un secondo fa).

Ho avuto questo problema.

Problemi correlati