Domanda

Quando si esegue un'istruzione ALTER TABLE in MySQL, l'intera tabella viene bloccata in lettura per la durata dell'istruzione. Se è una tabella di grandi dimensioni, ciò significa che le istruzioni di inserimento o aggiornamento potrebbero essere bloccate per un tempo davvero lungo. C'è un modo per fare un "hot alter", come aggiungere una colonna in modo tale che la tabella sia ancora aggiornabile durante tutto il processo?

Principalmente sono interessato a una soluzione per MySQL ma sarei interessato ad altri RDBMS se MySQL non può farlo.

Per chiarire, il mio scopo è semplicemente quello di evitare i tempi di inattività quando una nuova funzionalità che richiede una colonna di tabella aggiuntiva viene inviata alla produzione. Qualsiasi schema di database cambierà nel tempo, questo è solo un dato di fatto. Non vedo perché dovremmo accettare che questi cambiamenti debbano inevitabilmente causare tempi di inattività; è solo debole.

È stato utile?

Soluzione

L'unica altra opzione è fare manualmente ciò che fanno molti sistemi RDBMS ...
- Crea una nuova tabella

È quindi possibile copiare il contenuto della vecchia tabella su un blocco alla volta. Pur essendo sempre cauti nei confronti di INSERT / UPDATE / DELETE sulla tabella di origine. (Potrebbe essere gestito da un trigger. Anche se ciò causerebbe un rallentamento, non è un blocco ...)

Al termine, modificare il nome della tabella di origine, quindi cambiare il nome della nuova tabella. Preferibilmente in una transazione.

Al termine, ricompilare tutte le procedure memorizzate, ecc. che utilizzano quella tabella. I piani di esecuzione probabilmente non saranno più validi.

Modifica

Sono stati fatti alcuni commenti sul fatto che questa limitazione sia un po 'scarsa. Quindi ho pensato di mettere una nuova prospettiva su di esso per mostrare perché è come è ...

  • Aggiungere un nuovo campo è come cambiare un campo su ogni riga.
  • I blocchi di campo sarebbero molto più difficili dei blocchi di riga, non importa i blocchi di tabella.

  • In realtà stai cambiando la struttura fisica sul disco, ogni record si sposta.
  • Questo è davvero come un AGGIORNAMENTO sull'intero tavolo, ma con un impatto maggiore ...

Altri suggerimenti

Percona crea uno strumento chiamato pt-online-schema-change che consente di eseguire questa operazione.

Crea essenzialmente una copia della tabella e modifica la nuova tabella. Per mantenere la nuova tabella sincronizzata con l'originale, utilizza i trigger per l'aggiornamento. Ciò consente di accedere alla tabella originale mentre la nuova tabella viene preparata in background.

Questo è simile al metodo suggerito Dems sopra, ma lo fa in modo automatizzato.

Alcuni dei loro strumenti hanno una curva di apprendimento, in particolare la connessione al database, ma una volta che lo hai giù, sono ottimi strumenti da avere.

Esempio:

pt-online-schema-change --alter "ADD COLUMN c1 INT" D=db,t=numbers_are_friends

Questa domanda del 2009. Ora MySQL offre una soluzione:

DDL online

  

Una funzione che migliora le prestazioni, la concorrenza e la disponibilità   delle tabelle InnoDB durante le operazioni DDL (principalmente ALTER TABLE). Vedere   Sezione 14.11, & # 8220; InnoDB e DDL online & # 8221; per dettagli.

     

I dettagli variano in base al tipo di operazione. In alcuni casi,   la tabella può essere modificata contemporaneamente mentre è presente ALTER TABLE   progresso. L'operazione potrebbe essere in grado di essere eseguita senza eseguire a   copia da tavolo o utilizzando un tipo di copia da tavolo appositamente ottimizzato. Spazio   l'utilizzo è controllato da innodb_online_alter_log_max_size   opzione di configurazione.

Ti consente di regolare l'equilibrio tra prestazioni e concorrenza durante l'operazione DDL, scegliendo se bloccare completamente l'accesso alla tabella (LOCK = clausola ESCLUSIVA), consentire query ma non DML (LOCK = SHARED clausola) o consentire full query e accesso DML alla tabella (LOCK = clausola NONE). Quando si omette la clausola LOCK o si specifica LOCK = DEFAULT, MySQL consente la massima concorrenza possibile a seconda del tipo di operazione.

Eseguendo le modifiche sul posto laddove possibile, anziché creare una nuova copia della tabella, si evitano aumenti temporanei dell'utilizzo dello spazio su disco e dei costi di I / O associati alla copia della tabella e alla ricostruzione di indici secondari.

vedi Manuale di riferimento di MySQL 5.6 - > InnoDB e DDL online per maggiori informazioni.

Sembra che il DDL online sia disponibile anche in MariaDB

  

In alternativa puoi utilizzare ALTER ONLINE TABLE per assicurarti che ALTER   TABELLA non blocca le operazioni simultanee (non richiede blocchi). È   equivalente a LOCK = NONE.

MariaDB KB su ALTER TABLE

Vedi lo strumento di modifica dello schema online di Facebook.

http://www.facebook.com/notes / mysql-at-facebook / online-schema-cambio-di-mysql / 430801045932

Non per i deboli di cuore; ma farà il lavoro.

Raccomando Postgres se questa è un'opzione. Con Postgres non ci sono praticamente tempi morti con le seguenti procedure:

Un'altra grande caratteristica è che la maggior parte delle istruzioni DDL sono transazionali, quindi è possibile eseguire un'intera migrazione all'interno di una transazione SQL e, se qualcosa va storto, viene eseguito il rollback dell'intera cosa.

Ho scritto questo un po 'di tempo fa, forse può fare qualche approfondimento sugli altri meriti.

Dato che hai chiesto informazioni su altri database, ecco alcune informazioni su Oracle.

L'aggiunta di una colonna NULL a una tabella Oracle è un'operazione molto rapida in quanto aggiorna solo il dizionario dei dati. Questo contiene un blocco esclusivo sul tavolo per un periodo di tempo molto breve. Tuttavia, invaliderà qualsiasi stored procedure, viste, trigger ecc. Memorizzati. Verranno ricompilati automaticamente.

Da lì, se necessario, è possibile creare un indice utilizzando la clausola ONLINE. Ancora una volta, solo i blocchi del dizionario dei dati molto brevi. Leggerà l'intero tavolo alla ricerca di cose da indicizzare, ma non blocca nessuno mentre lo fa.

Se è necessario aggiungere una chiave esterna, è possibile farlo e far credere a Oracle che i dati siano corretti. In caso contrario, è necessario leggere l'intera tabella e convalidare tutti i valori che possono essere lenti (creare prima l'indice).

Se devi inserire un valore predefinito o calcolato in ogni riga della nuova colonna, dovrai eseguire un aggiornamento massiccio o forse un piccolo programma di utilità che popola i nuovi dati. Questo può essere lento, specialmente se le file diventano molto più grandi e non si adattano più ai loro blocchi. Il blocco può essere gestito durante questo processo. Poiché il vecchio versino dell'applicazione, che è ancora in esecuzione, non è a conoscenza di questa colonna, potresti aver bisogno di un trigger subdolo o di specificare un valore predefinito.

Da lì, puoi eseguire uno switcharoo sui tuoi server delle applicazioni alla nuova versione del codice e continuerà a funzionare. Rilascia il grilletto subdolo.

In alternativa, puoi usare DBMS_REDEFINITION che è una scatola nera progettata per fare questo genere di cose.

Tutto questo è così fastidioso da testare, ecc. che abbiamo appena un'interruzione di domenica mattina presto ogni volta che rilasciamo una versione principale.

Se non è possibile permettersi tempi di inattività del database durante gli aggiornamenti delle applicazioni, è necessario considerare la gestione di un cluster a due nodi per la disponibilità elevata. Con una semplice configurazione della replica, è possibile apportare modifiche strutturali quasi completamente online come quella che si suggerisce:

  • attendi che tutte le modifiche vengano replicate su uno slave passivo
  • cambia lo slave passivo in modo che diventi il ??master attivo
  • apporta le modifiche strutturali al vecchio maestro
  • replica le modifiche dal nuovo master al vecchio master
  • esegui di nuovo lo scambio principale e la distribuzione della nuova app contemporaneamente

Non è sempre facile ma funziona, di solito con 0 tempi di inattività! Il secondo nodo non deve essere solo passivo, può essere utilizzato per test, statistiche o come nodo di fallback. Se non si dispone della replica dell'infrastruttura, è possibile impostare una singola macchina (con due istanze di MySQL).

No. Se stai usando le tabelle MyISAM, per quanto ne so, fanno solo blocchi di tabelle - non ci sono blocchi di record, cercano solo di mantenere tutto iperveloce attraverso la semplicità. (Altre tabelle MySQL funzionano in modo diverso.) In ogni caso, è possibile copiare la tabella in un'altra tabella, modificarla e quindi cambiarla, aggiornando per differenze.

Questa è un'alterazione così grande che dubito che qualsiasi DBMS possa supportarla. È considerato in primo luogo un vantaggio poterlo fare con i dati nella tabella.

Soluzione temporanea ...

Un'altra soluzione potrebbe essere, aggiungere un'altra tabella con la chiave primaria della tabella originale, insieme alla nuova colonna.

Popolare la chiave primaria nella nuova tabella e popola i valori per la nuova colonna nella nuova tabella e modifica la query per unire questa tabella per le operazioni selezionate e devi anche inserire, aggiornare separatamente per questo valore di colonna.

Quando è possibile ottenere tempi di inattività, è possibile modificare la tabella originale, modificare le query DML e eliminare la nuova tabella creata in precedenza

Altrimenti, puoi scegliere il metodo di clustering, la replica, lo strumento di schema pt-online di percona

Utilizzando il plug-in Innodb, le istruzioni ALTER TABLE che aggiungono o eliminano solo gli indici secondari possono essere eseguite "rapidamente", ovvero senza ricostruire la tabella.

In generale, tuttavia, in MySQL, qualsiasi ALTER TABLE comporta la ricostruzione dell'intera tabella che può richiedere molto tempo (ovvero se la tabella contiene una quantità utile di dati).

Devi davvero progettare la tua applicazione in modo che le istruzioni ALTER TABLE non debbano essere eseguite regolarmente; sicuramente non vuoi che ALTER TABLE venga eseguito durante il normale funzionamento dell'applicazione a meno che non sei pronto ad aspettare o stai modificando piccoli tavoli.

Vorrei raccomandare uno dei due approcci:

  1. Progetta le tue tabelle di database tenendo conto delle potenziali modifiche. Ad esempio, ho lavorato con i sistemi di gestione dei contenuti, che cambiano regolarmente i campi di dati nei contenuti. Invece di costruire la struttura fisica del database per soddisfare i requisiti iniziali del campo CMS, è molto meglio costruire in una struttura flessibile. In questo caso, usando un campo di testo BLOB (varchar (max) per esempio) per contenere dati XML flessibili. Ciò rende i cambiamenti strutturali molto meno frequenti. I cambiamenti strutturali possono essere costosi, quindi anche qui c'è un vantaggio.

  2. Avere tempo di manutenzione del sistema. Il sistema non è in linea durante le modifiche (mensili, ecc.) E le modifiche sono programmate durante l'ora meno trafficata della giornata (3-5, ad esempio). Le modifiche vengono messe in scena prima dell'implementazione della produzione, quindi avrai una buona stima della finestra fissa dei tempi di fermo.

2a. Hanno server ridondanti, in modo che quando il sistema ha tempi di inattività, l'intero sito non si arresti. Ciò ti consentirebbe di "rollare" i tuoi aggiornamenti in modo sfalsato, senza abbattere l'intero sito.

Le opzioni 2 e 2a potrebbero non essere fattibili; tendono ad essere solo per siti / operazioni più grandi. Sono opzioni valide, tuttavia, e ho usato personalmente tutte le opzioni presentate qui.

Se qualcuno sta ancora leggendo questo o capita di venire qui, questo è il grande vantaggio dell'utilizzo di un sistema di database NoSQL come mongodb. Ho avuto lo stesso problema con l'alterazione della tabella per aggiungere colonne per funzionalità aggiuntive o indici su una tabella di grandi dimensioni con milioni di righe e scritture alte. Si bloccherebbe per molto tempo, quindi farlo sul database LIVE frustrerebbe i nostri utenti. Sui tavolini puoi cavartela.

Odio il fatto che dobbiamo "progettare le nostre tabelle per evitare di modificarle". Non penso che funzioni nel mondo dei siti Web di oggi. Non puoi prevedere in che modo le persone useranno il tuo software, ecco perché cambi rapidamente le cose in base al feedback degli utenti. Con mongodb, puoi aggiungere " colonne " a volontà senza tempi di fermo. Non li aggiungi nemmeno, inserisci semplicemente i dati con nuove colonne e lo fa automaticamente.

Vale la pena dare un'occhiata: www.mongodb.com

In generale, la risposta sarà " No " ;. Stai modificando la struttura della tabella che potenzialmente richiederà molti aggiornamenti " e sono assolutamente d'accordo. Se ti aspetti di farlo spesso, ti offro un'alternativa a "fittizio" colonne: usa VIEW anziché le tabelle per i dati SELECT . IIRC, la modifica della definizione di una vista è relativamente leggera e la direzione indiretta attraverso una vista viene eseguita quando viene compilato il piano di query. La spesa è che dovresti aggiungere la colonna a una nuova tabella e rendere la vista JOIN nella colonna.

Ovviamente questo funziona solo se puoi usare chiavi esterne per eseguire il collegamento a cascata di eliminazioni e quant'altro. L'altro vantaggio è che puoi creare una nuova tabella contenente una combinazione di dati e indicarne la vista senza disturbare l'utilizzo del client.

Solo un pensiero.

La differenza tra Postgres e MySQL a questo proposito è che in Postgres non ricrea una tabella, ma modifica un dizionario di dati simile a Oracle. Pertanto, l'operazione è veloce, mentre richiede ancora di allocare un blocco esclusivo della tabella DDL per un tempo molto breve, come affermato in precedenza da altri.

In MySQL l'operazione copierà i dati in una nuova tabella mentre blocca le transazioni, il che è stato il principale problema per i DBA MySQL prima di v. 5.6.

La buona notizia è che dalla versione di MySQL 5.6 la restrizione è stata principalmente sollevato e ora puoi goderti la vera potenza del DB MYSQL.

Come accennato da SeanDowney, pt-online-schema-change è uno dei migliori strumenti per fare ciò che è stato descritto nella domanda qui. Di recente ho apportato molte modifiche allo schema su un DB live ed è andato abbastanza bene. Puoi leggere di più a riguardo sul mio post sul blog qui: http://mrafayaleem.com/2016/02/08/live-mysql-schema-changes-with-percona/ .

Dovresti assolutamente provare pt-online-schema-change . Ho utilizzato questo strumento per eseguire migrazioni su AWS RDS con più slave e ha funzionato molto bene per me. Ho scritto un post sul blog elaborato su come fare ciò che potrebbe essere utile per te.

Blog: http://mrafayaleem.com / 2016/02/08 / live-mysql-schema-cambiamenti-con-Percona /

Le colonne fittizie sono una buona idea se puoi prevederne il tipo (e renderle nullable). Controlla come il tuo motore di archiviazione gestisce i null.

MyISAM bloccherà tutto se si menziona anche il nome di un tavolo passando, al telefono, all'aeroporto. Lo fa solo ...

Detto questo, le serrature non sono un grosso problema; fintanto che non stai cercando di aggiungere un valore predefinito per la nuova colonna a ogni riga, ma lascia che sia posizionato come nullo e il tuo motore di archiviazione è abbastanza intelligente da non andare a scriverlo, dovresti essere a posto con un lucchetto che è solo tenuto abbastanza a lungo per aggiornare i metadati. Se provi a scrivere un nuovo valore, beh, sei un brindisi.

TokuDB può aggiungere / rilasciare colonne e aggiungere indici "caldi", la tabella è completamente disponibile durante tutto il processo. È disponibile tramite www.tokutek.com

Non proprio.

Dopotutto, STAI modificando la struttura sottostante della tabella, e questo è un po 'di informazioni che è abbastanza importante per il sistema sottostante. Stai anche (probabilmente) spostando gran parte dei dati sul disco.

Se hai intenzione di farlo molto, è meglio semplicemente riempire la tabella con "fittizio". colonne disponibili per uso futuro.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top