Come posso configurare MySQL Innodb per gestire 1000s di inserti all'ora?


10

Ho un sito Web a traffico molto elevato in cui è possibile che ogni ora vengano inseriti migliaia di nuovi record.

Questo errore sta paralizzando il sito:

PDOException: SQLSTATE[40001]: Serialization failure: 1213 
Deadlock found when trying to get lock; 
try restarting transaction: INSERT INTO {location_instance} 
(nid, vid, uid, genid, lid) VALUES (:db_insert_placeholder_0, 
:db_insert_placeholder_1, :db_insert_placeholder_2, 
:db_insert_placeholder_3, :db_insert_placeholder_4); 
Array ( [:db_insert_placeholder_0] => 1059 [:db_insert_placeholder_1] => 
1059 [:db_insert_placeholder_2] => 0 [:db_insert_placeholder_3] => 
cck:field_item_location:1059 [:db_insert_placeholder_4] => 1000 )

Sarei molto sorpreso se MySQL non fosse in grado di gestire questo tipo di carico. Quindi, le mie domande sono quindi: si tratta di un problema di database e come posso configurare MySQL per essere in grado di gestire questo traffico?

Ho una copia del mio sito Web impostata su un server di sviluppo con script che simulano il carico di contenuti aggiunti al sito Web. Sto eseguendo Ubuntu, stack LAMP, con 16 GB di RAM.

Certo, non sono molto ben informato sui database. In effetti, sto iniziando con my.cnf predefinito che viene fornito al termine di 'apt-get install'. Le tabelle sono tutte Innodb. Quali impostazioni e impostazioni di configurazione iniziali consiglieresti di iniziare a risolvere questo problema?

Fammi sapere quali ulteriori informazioni potresti aver bisogno.

Grazie


Stai iniziando con my.cnf predefinito per la produzione? Amico, devi ottimizzarlo di più. Ti spiegherò di più nella mia risposta. :-)

Risposte:


11

Stai affrontando un deadlock, non un problema di collo di bottiglia delle prestazioni.

Se hai un migliaio di nuovi record all'ora, sei molto lontano dal raggiungere i limiti di MySQL. MySQL è in grado di gestire almeno 50 volte il carico.

I deadlock sono causati dal codice dell'applicazione e non sono un errore del server di database. I deadlock non possono essere risolti sul lato server MySQL, tranne in alcune situazioni specifiche.

InnoDBpuò mostrare informazioni dettagliate sul deadlock eseguendo SHOW ENGINE INNODB STATUSal prompt di MySQL o con mysql -uroot -p... -e "SHOW ENGINE INNODB STATUS".

Tuttavia, questo mostra solo l'ultimo deadlock che si è verificato, non esiste un registro deadlock.

Per fortuna, c'è uno strumento pt-deadlock-logger che si occupa di quel problema, si occupa dello InnoDBstato di polling e salva tutte le informazioni dettagliate sui deadlock prima che vengano aggiornate con un nuovo deadlock.


Buono a sapersi! Nel comando show status vedo le informazioni sul blocco e sulla relativa query e tabella. Dato che questo è nel mio codice, come posso usare queste informazioni dal comando status per iniziare il debug del problema? La query PHP PDO è piuttosto semplice: connetti, prepara, esegui, ripeti. Sarei felice di pubblicare qualsiasi codice o messaggio di stato se ciò potesse aiutare.
user658182

@ user658182 controlla questo post su stackoverflow su come gestire i deadlock: come evitare i deadlock mysql trovati quando provi a ottenere il blocco
Valor

1
@ max-vernon grazie per la modifica della sintassi, chiaramente l'inglese non è la mia lingua madre :-).
Valor

1
-e "SHOW ENGINE INNODB STATUS"
glifo

8

Potrebbe essere semplice come una parte del codice che esegue una transazione:

insert into t1...
insert into t2...
commit;

mentre un'altra parte del codice modifica le stesse tabelle in un ordine diverso:

delete from t2 where...
delete from t1 where...
commit;

Se entrambe le transazioni vengono eseguite contemporaneamente, può verificarsi una condizione di competizione: la prima transazione non può essere modificata t2poiché è bloccata dalla seconda transazione; mentre la seconda transazione è bloccata in modo simile perché t1è bloccata dalla prima transazione. MySQL sceglie una transazione come "vittima" in cui INSERT / UPDATE / DELETE falliscono. L'applicazione deve rilevare quell'errore e riprovare la dichiarazione, magari dopo una pausa, in modo che l'altra transazione abbia il tempo di terminare. Niente a che vedere con i limiti di capacità, solo tempi sfavorevoli che possono essere aggravati dal modo in cui il codice è organizzato. Passa dal DELETE alla transazione n. 2 o agli INSERISCI nella transazione n. 1, quindi non si verificano conflitti: ogni transazione attenderà l'accesso alle tabelle necessarie.

In MySQL 5.6, è possibile eseguire l' opzione innodb_print_all_deadlocks abilitata per raccogliere informazioni su tutti i deadlock (non solo quello più recente) nel log degli errori di MySQL.

[Dichiarazione di non responsabilità obbligatoria: sono un dipendente Oracle. Quanto sopra è la mia opinione personale, non una dichiarazione ufficiale.]

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.