[2017] Aggiornamento: MySQL 5.6 supporta gli aggiornamenti dell'indice online
https://dev.mysql.com/doc/refman/8.0/en/innodb-online-ddl-operations.html#online-ddl-index-syntax-notes
In MySQL 5.6 e versioni successive, la tabella rimane disponibile per le operazioni di lettura e scrittura durante la creazione o l'eliminazione dell'indice. L'istruzione CREATE INDEX o DROP INDEX termina solo dopo che tutte le transazioni che accedono alla tabella sono state completate, in modo che lo stato iniziale dell'indice rifletta il contenuto più recente della tabella. In precedenza, la modifica della tabella durante la creazione o l'eliminazione di un indice in genere causava un deadlock che annullava l'istruzione INSERT, UPDATE o DELETE sulla tabella.
[2015] L'aggiornamento della tabella indica che blocca le scritture in MySQL 5.5
Dalla risposta sopra:
"Se utilizzi una versione superiore alla 5.1, gli indici vengono creati mentre il database è online. Quindi non preoccuparti, non interromperai l'utilizzo del sistema di produzione."
Questo è **** FALSO **** (almeno per le tabelle MyISAM / InnoDB, che è ciò che usa il 99,999% delle persone là fuori. L'edizione cluster è diversa.)
L'esecuzione di operazioni di AGGIORNAMENTO su una tabella si BLOCCA durante la creazione dell'indice. MySQL è davvero, davvero stupido su questo (e su poche altre cose).
Script di test:
(
for n in {1..50}; do
#(time mysql -uroot -e 'select * from website_development.users where id = 41225\G'>/dev/null) 2>&1 | grep real;
(time mysql -uroot -e 'update website_development.users set bio="" where id = 41225\G'>/dev/null) 2>&1 | grep real;
done
) | cat -n &
PID=$!
sleep 0.05
echo "Index Update - START"
mysql -uroot website_development -e 'alter table users add index ddopsonfu (last_name, email, first_name, confirmation_token, current_sign_in_ip);'
echo "Index Update - FINISH"
sleep 0.05
kill $PID
time mysql -uroot website_development -e 'drop index ddopsonfu on users;'
Il mio server (InnoDB):
Server version: 5.5.25a Source distribution
Output (notare come la sesta operazione si blocca per i ~ 400 ms necessari per completare l'aggiornamento dell'indice):
1 real 0m0.009s
2 real 0m0.009s
3 real 0m0.009s
4 real 0m0.012s
5 real 0m0.009s
Index Update - START
Index Update - FINISH
6 real 0m0.388s
7 real 0m0.009s
8 real 0m0.009s
9 real 0m0.009s
10 real 0m0.009s
11 real 0m0.009s
Vs operazioni di lettura che non bloccano (scambia il commento di riga nello script):
1 real 0m0.010s
2 real 0m0.009s
3 real 0m0.009s
4 real 0m0.010s
5 real 0m0.009s
Index Update - START
6 real 0m0.010s
7 real 0m0.010s
8 real 0m0.011s
9 real 0m0.010s
...
41 real 0m0.009s
42 real 0m0.010s
43 real 0m0.009s
Index Update - FINISH
44 real 0m0.012s
45 real 0m0.009s
46 real 0m0.009s
47 real 0m0.010s
48 real 0m0.009s
Aggiornamento dello schema di MySQL senza tempi di inattività
Finora, c'è solo un metodo che conosco per aggiornare uno schema MySql e non subire un'interruzione della disponibilità. Maestri circolari:
- Il Master A ha il tuo database MySQL in esecuzione su di esso
- Metti in servizio il Master B e fallo replicare le scritture dal Master A (B è uno schiavo di A)
- Eseguire l'aggiornamento dello schema su Master B. Rimarrà indietro durante l'aggiornamento
- Lascia che il Maestro B raggiunga. Invariant: la modifica dello schema DEVE essere in grado di elaborare comandi replicati da uno schema downversion. Le modifiche all'indicizzazione si qualificano. Solitamente si qualificano semplici aggiunte di colonne. Rimuovere una colonna? probabilmente no.
- Scambia ATOMICAMENTE tutti i client dal Master A al Master B. Se vuoi essere al sicuro (credimi, lo fai), dovresti assicurarti che l'ultima scrittura su A sia replicata su B PRIMAB esegue la prima scrittura. Se consenti le scritture simultanee su 2+ master, ... comprendi meglio la replica di MySQL a un livello PROFONDO o sei destinato a un mondo di dolore. Dolore estremo. Ad esempio, hai una colonna AUTOINCREMENT ??? sei fregato (a meno che non usi i numeri pari su un master e le probabilità sull'altro). NON fidarti della replica di MySQL per "fare la cosa giusta". NON è intelligente e non ti salverà. È solo leggermente meno sicuro che copiare i registri delle transazioni binarie dalla riga di comando e riprodurli a mano. Tuttavia, disconnettere tutti i client dal vecchio master e spostarli nel nuovo master può essere eseguito in pochi secondi, molto più velocemente dell'attesa per un aggiornamento dello schema di più ore.
- Ora il Maestro B è il tuo nuovo maestro. Hai il nuovo schema. La vita è bella. Prendere una birra; il peggio è passato.
- Ripeti il processo con il Master A, aggiornando il suo schema in modo che diventi il tuo nuovo master secondario, pronto a subentrare nel caso in cui il tuo master primario (master B ora) perda potenza o semplicemente su e muore su di te.
Un modo semplice per aggiornare lo schema non lo è. Realizzabile in un ambiente di produzione serio; sì. Per favore, per favore, per favore, se c'è un modo più semplice per aggiungere un indice a una tabella MySQL senza bloccare le scritture, fammelo sapere.
Google mi ha portato a questo articolo che descrive una tecnica simile. Ancora meglio, consigliano di bere nello stesso punto della procedura (Nota che ho scritto la mia risposta prima di leggere l'articolo)!
La modifica dello schema online di Percona
L' articolo che ho collegato sopra parla di uno strumento, pt-online-schema-change , che funziona come segue:
- Crea una nuova tabella con la stessa struttura dell'originale.
- Aggiorna lo schema sulla nuova tabella.
- Aggiungi un trigger alla tabella originale in modo che le modifiche siano mantenute sincronizzate con la copia
- Copia le righe in batch dalla tabella originale.
- Spostare la tabella originale fuori mano e sostituirla con una nuova tabella.
- Lascia cadere il vecchio tavolo.
Non ho mai provato lo strumento da solo. YMMV
RDS
Attualmente sto utilizzando MySQL tramite RDS di Amazon . È un servizio davvero ingegnoso che avvolge e gestisce MySQL, permettendoti di aggiungere nuove repliche di lettura con un solo pulsante e aggiornare in modo trasparente il database attraverso gli SKU hardware. È davvero conveniente. Non hai un accesso SUPER al database, quindi non puoi fottere direttamente la replica (è una benedizione o una maledizione?). Tuttavia, è possibile utilizzare la promozione della replica in lettura per apportare modifiche allo schema su uno slave di sola lettura, quindi promuovere tale slave affinché diventi il nuovo master. Esattamente lo stesso trucco che ho descritto sopra, solo molto più facile da eseguire. Non fanno ancora molto per aiutarti con il cut-over. Devi riconfigurare e riavviare la tua app.