Modifica di colonne di tabelle mysql molto grandi con tempi di inattività ridotti o nulli


18

Devo periodicamente apportare modifiche alle tabelle in mysql 5.1, aggiungendo principalmente colonne. Molto semplice con il comando alter table. Ma le mie tabelle ora hanno fino a 40 milioni di righe e stanno crescendo rapidamente ... Quindi quei comandi alter table richiedono diverse ore. Tra un paio di mesi ci vorranno giorni immagino.

Dal momento che sto usando Amazon RDS, non posso avere server slave con cui giocare e quindi promuovere da master. Quindi la mia domanda è se c'è un modo per farlo con tempi di fermo minimi? Non mi dispiace un'operazione che richiede ore o addirittura giorni se gli utenti possono ancora usare il db ovviamente ... Possono almeno leggere mentre le colonne vengono aggiunte? Cosa succede se la mia app tenta di scrivere? Inserisci o aggiorna? Se fallisce immediatamente non è poi così male, se si blocca e causa problemi al server db, questo è un grosso problema.

Questo deve essere un problema di ridimensionamento abbastanza comune, tutti hanno bisogno di aggiungere colonne .. Che cosa viene in genere fatto a un db di produzione? Slave -> migrazione principale?

Aggiornamento - Ho dimenticato di menzionare che sto usando il motore di archiviazione innodb


1
Nel caso in cui qualcuno stia ancora cercando una risposta .. blog.staginginstance.com/… ^^
Coder anonimo

Risposte:


10

Devo periodicamente apportare modifiche alle tabelle in mysql 5.1, aggiungendo principalmente colonne.

Non farlo. No davvero. Non farlo. Dovrebbe essere un'occasione molto rara in cui ciò sia mai necessario.

Supponendo che i tuoi dati siano davvero normalizzati per cominciare, il modo giusto per risolvere il problema è aggiungere una nuova tabella con una relazione 1: 1 alla tabella di base (non obbligatoria sulla nuova tabella).

Dover aggiungere regolarmente colonne è di solito un indicatore di un database che non è normalizzato - se lo schema non è normalizzato, questo è il problema che devi risolvere.

Infine, se il tuo schema è davvero, è davvero normalizzato e devi davvero continuare ad aggiungere colonne:

  1. Assicurati di avere una colonna timestamp sul database o che stia generando i log di replica
  2. Crea una copia (B) della tabella (A)
  3. aggiungi le nuove colonne a B (questo si bloccherà comunque con myisam)
  4. disabilitare le transazioni
  5. rinominare la tabella originale (A) come qualcos'altro (backup)
  6. rinominare la nuova tabella (B) con il nome della tabella originale (A)
  7. riprodurre le transazioni dall'inizio dell'operazione dal registro di replica o dalla tabella di backup
  8. abilitare le transazioni.

2
Grazie per l'approccio graduale. È davvero raro modificare le tabelle? Capisco che posso invece aggiungere un'altra tabella con la nuova colonna (nel caso in cui sia necessario aggiungere una colonna) e fare in modo che faccia riferimento alla tabella grande originale in una relazione 1: 1. Ma non sembra giusto avere 15 tabelle 1: 1 molto grandi quando dovrebbero essere tutte in 1 tabella ... Anche le prestazioni di query ovviamente soffrono, per non parlare dei problemi di indicizzazione. Non sono un esperto, ma il mio database è abbastanza ben normalizzato e sembra naturale che debba modificare periodicamente ..
apptree

2
"È davvero raro modificare le tabelle?" - Sì.
symcbean,

1
No, ma si può sostenere che se ciò accade REGOLARMENTE - non come parte di un importante aggiornamento del software - allora qualcuno deve essere licenziato per non rendersi conto che tutti i tavoli dovrebbero essere lì in primo luogo. Il problema / trucco qui è il "regolarmente", non "Una volta ogni due mesi".
TomTom,

22
Come sviluppatore, in particolare uno che lavora in start-up e giovani aziende, non potrei essere meno d'accordo con Symcbean e @TomTom. Le cose cambiano, i prodotti cambiano, gli obiettivi aziendali cambiano e la struttura del database deve cambiare con loro. Fornire un buon servizio DBA significa dire "sì" a tali modifiche, quindi capire come implementarle in modo efficiente. Database fortemente normalizzati sono un concetto che è morto molto tempo fa. Ne risultano prestazioni scadenti e cicli di sviluppo lenti.
pents90,

4
Non comune cambiare tabella ??? Forse nelle grandi aziende, ma in un team agile che accade abbastanza spesso, i requisiti cambiano ...
Tibo

12

Ho dovuto farlo di recente. Ciò che Amazon ha raccomandato è stato l'utilizzo del Percona Toolkit. L'ho scaricato ed è stato in grado di eseguire qualcosa del tipo:

./pt-online-schema-change h=databasenameHostName,D=databasename,t=tablename --recursion-method=none --execute --user username --password password --alter "MODIFY someColumn newDataType"

e funziona benissimo. Ti dice quanto tempo rimane nel processo.

In realtà crea una nuova tabella con la nuova colonna e quindi copia i dati esistenti. Inoltre, crea un trigger in modo che anche i nuovi dati vengano trasferiti nella nuova tabella. Quindi rinomina automaticamente le tabelle, elimina la vecchia tabella e sei attivo e funzionante con la nuova colonna e nessun tempo di inattività mentre aspetti gli aggiornamenti.


Il team di Percona ha una breve descrizione dell'abilitazione della funzione log_bin_trust_function_creators, attraverso gruppi di parametri RDS (poiché SET GLOBAL log_bin_trust_function_creators = 1 non funziona su RDS), richiesto dallo strumento pt-online-schema-change. Maggiori dettagli: percona.com/blog/2016/07/01/pt-online-schema-change-amazon-rds
user1652110

ha funzionato per me
Adiii

4

symcbean fornisce alcuni solidi consigli .

Per rispondere alla tua domanda, il modo più semplice e migliore per mitigare l'impatto consiste nel replicare più database. Dual master con una procedura di failover appropriata che interrompe la replica sull'attivo, che consente un'alterazione sull'inattivo senza influire sull'attivo.

Potresti potenzialmente farlo su un singolo database live e minimizzare l'impatto usando una procedura simile a quella che ho dettagliato in questa risposta . Certo, questo è simile a quello descritto da Symcbean ma include dettagli tecnici. È possibile utilizzare anche un campo auto_increment e non solo il timestamp.

In definitiva, se il tuo set di dati sta diventando così grande, devi anche considerare l'archiviazione tra database OLTP e OLAP . Il set di dati della transazione non dovrebbe essere così grande, se progettato in modo appropriato.


2

Dal manuale: http://dev.mysql.com/doc/refman/5.1/en/alter-table.html

Nella maggior parte dei casi, ALTER TABLE crea una copia temporanea della tabella originale. MySQL incorpora l'alterazione nella copia, quindi elimina la tabella originale e rinomina quella nuova. Durante l'esecuzione di ALTER TABLE, la tabella originale è leggibile da altre sessioni. Gli aggiornamenti e le scritture nella tabella vengono bloccati fino a quando la nuova tabella non è pronta, quindi vengono automaticamente reindirizzati alla nuova tabella senza aggiornamenti non riusciti.

Quindi, la lettura funzionerà bene. Le scritture verranno bloccate, ma eseguite successivamente. Se vuoi impedirlo, dovrai modificare il tuo software.


Quindi ho fatto questo e disabilitato le parti del mio sito che scrivono sulla tabella che sto modificando in questo momento. Finora ho ricevuto diverse eccezioni "Blocco del timeout di attesa superato; prova a riavviare la transazione", non è male. Tuttavia, erano in PURAMENTE operazioni di lettura ...
circa

0

Sono in una situazione simile in cui devo modificare 1 della mia tabella delle transazioni che è quasi 65 GB. Sento 2 soluzioni

  1. Usa ALTER direttamente e lascialo correre (X numeri di ore o giorno)
  2. Assicurati di avere una colonna timestamp sul database o che stia generando i log di replica
    • Crea una copia (B) della tabella (A)
    • aggiungi le nuove colonne a B (questo si bloccherà comunque con myisam)
    • disabilitare le transazioni
    • rinominare la tabella originale (A) come qualcos'altro (backup)
    • rinominare la nuova tabella (B) con il nome della tabella originale (A)
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.