modo per impedire alle query di attendere il blocco a livello di tabella


10

Abbiamo riscontrato un problema dopo aver spostato il database dei nostri clienti su un server aggiuntivo. Ciò avrebbe dovuto avere effetti positivi sulle prestazioni del sito, ma si è verificato un problema con il blocco delle tabelle in MyISAM. (Ho sentito di usare InnoDB invece di MyISAM, ma non possiamo cambiare il motore nel prossimo futuro).
Potremmo individuarlo in una query di aggiornamento che viene eseguita quando un moderatore attiva un commento sul sito. Questo è il processo:

  • la query di aggiornamento viene elaborata SET status = 1 WHERE id = 5(l'indice è impostato)
  • i file memorizzati nella cache della pagina vengono eliminati

A questo punto l'intera pagina diventa lenta. Il database stesso è occupato per minuti. Ho recuperato l'elenco dei processi alcune volte e ho visto circa 60 voci di diverse query di selezione, tutte in attesa dello stato di blocco a livello di tabella .

1. Non capisco perché questo aggiornamento sulla tabella article_commentspossa influenzare le istruzioni select per la tabella articlein attesa del blocco a livello di tabella. Nella processlist quasi tutte le query in attesa provenivano da questa tabella. Ho letto del fatto che gli aggiornamenti / inserimenti sono preferiti alle selezioni e che ciò può causare tali problemi, ma la stessa tabella degli articoli non viene aggiornata quando i commenti vengono attivati, quindi le selezioni non dovrebbero attendere. L'ho sbagliato?
2. C'è qualcosa oltre a passare a InnoDB per prevenire questo comportamento o almeno per ottenere un migliore equilibrio? Sono molto irritato dal fatto che questo problema non si sia verificato prima di spostare il database sul nuovo server. Immagino che ci sia qualche configurazione errata ma non so come identificarmi.


1
Abilita la registrazione generale e controlla le istruzioni JOIN tra queste tabelle. Quando si seleziona, crea un READ LOCK implicito. Poiché MYISAM non supporta il blocco ROW LEVEL, si blocca a livello di tabella. È probabilmente il caso che questo blocco si stesse verificando sul vecchio server ma nessuno stava guardando? Confronta la tua linea my.cnf per la linea tra host e soprattutto assicurati che il tuo key_buffer sia sintonizzato correttamente.
randomx,

Abbiamo avuto diversi altri problemi di prestazioni sul vecchio server e spesso abbiamo guardato l'elenco dei processi. Ci sono stati principalmente molti processi di sospensione, ma non abbiamo mai notato quelli in attesa (ho visto queste informazioni generalmente la prima volta su questo nuovo server). Il mio collega ha copiato il vecchio my.cnf e adattato i valori al nuovo hardware esistente, ma non c'erano molte voci. Ho anche confrontato le uscite di "SHOW VARIABLES" ma non sapevo davvero cosa cercare. Domani ricontrolleremo il keybuffer, grazie per il tuo commento.
32bitfloat,

Di recente abbiamo avuto un problema simile. Inizialmente il nostro key_buffer_sizeera impostato su 1GB. Aumentando quello per 10GBridurre il problema.
Haluk,

@ Rick James, grazie. Mi hai risparmiato un sacco di problemi oggi. Hai una lista dei desideri in Amazon o altrove? :) Ho impostato query_cache_limit su 1024. Non ci sono problemi di blocco ora. L'ho fatto inizialmente in variabili dal client mysql. set global query_cache_limit = 1024; Ora lo scriverò su my.cnf. Questa soluzione mi ha dato il tempo di pianificare la migrazione innodb senza stress, quindi grazie.

Risposte:


8

MyISAM Storage Engine è furiosamente noto per l'esecuzione di blocchi di tabelle complete per qualsiasi DML (INSERT, UPDATE, DELETE). InnoDB risolverà definitivamente questo problema a lungo termine.

Ho scritto di pro e contro dell'utilizzo di MyISAM vs InnoDB

Per quanto riguarda la tua domanda attuale, ecco un possibile scenario:

  • articlee article_commentssono entrambe le tabelle MyISAM
  • article_commentsha uno o più indici con statuscome colonna
  • Gli aggiornamenti delle pagine dell'indice per article_commentsvengono memorizzati nella cache del buffer delle chiavi MyISAM (dimensionato da key_buffer_size ), causando le vecchie pagine dell'indice dal buffer delle chiavi MyISAM
  • Sono presenti query SELECT che eseguono JOIN tra articleearticle_comments

Nel mio scenario suggerito, SELECTs rispetto al articletavolo può essere trattenuto dal consentire le scritture a causa della necessità di attendere la liberazione article_commentsda qualsiasi DML (in questo caso, un UPDATE)


Grazie per la tua risposta (e i link), il tuo scenario è reale. Non mi sono reso conto che la maggior parte dell'articolo selezionato si unisce alla tabella dei commenti (o, in altre parole, ha visto le dichiarazioni incomplete nella lista di processi di phpmyadmin). Conosci una soluzione a breve termine per prevenire le domande multiple in attesa? L'ho già provato con "UPDATE LOW_PRIORITY" nell'istruzione specifica ma ciò non ha apportato modifiche evidenti. Passeremo davvero a innodb in futuro, ma mi chiedo se al momento sia possibile ottenere un miglioramento.
32bitfloat,

Soluzione definitiva: converti le tabelle in InnoDB. Vedi il mio post dba.stackexchange.com/a/9422/877 su come convertire tutto MyISAM in InnoDB
RolandoMySQLDBA

7

A questo punto l'intera pagina diventa lenta. Il database stesso è occupato per minuti.

Odori come se avessi una grande Query_cache?

mysql> SHOW VARIABLES LIKE 'query_cache%';
+------------------------------+----------+
| Variable_name                | Value    |
+------------------------------+----------+
| query_cache_limit            | 1048576  |
| query_cache_min_res_unit     | 4096     |
| query_cache_size             | 16777216 | -- Not over 50M
| query_cache_type             | DEMAND   | -- Only if using SQL_CACHE
| query_cache_wlock_invalidate | OFF      |
+------------------------------+----------+

Per i sistemi di produzione con molte scritture, puoi anche disattivare query_cache.

Tutte le voci in query_cache per la tabella specificata vengono eliminate quando si verifica una scrittura su quella tabella. Maggiore è il controllo qualità, più lento è questo compito.

MyISAM utilizza blocchi "a livello di tabella". Lettura e scrittura non possono avvenire contemporaneamente (sulla stessa tabella). Crudo, ma efficace.


1
Beh si. Abbiamo circa 64 milioni di cache. Grazie per questa informazione che era nuova per me, tuttavia, avevamo lo stesso valore sul vecchio server in cui non avevamo notato i tablelockings. Abbiamo già iniziato a passare a InnoDB ma questo fatto rimane un mistero ...
32bitfloat
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.