Mysql
 sql >> Database >  >> RDS >> Mysql

Crea un indice su un'enorme tabella di produzione MySQL senza il blocco della tabella

Aggiornamento [2017]:MySQL 5.6 supporta gli aggiornamenti degli indici 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 il completamento di tutte le transazioni che accedono alla tabella, 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 generava in genere un deadlock che annullava l'istruzione INSERT, UPDATE o DELETE sulla tabella.

[2015] Aggiornamento delle scritture dei blocchi degli indici delle tabelle in MySQL 5.5

Dalla risposta sopra:

"Se stai utilizzando 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. Clustered Edition è diverso.)

L'esecuzione di operazioni di AGGIORNAMENTO su una tabella BLOCCO durante la creazione dell'indice. MySQL è davvero, davvero stupido su questo (e poche altre cose).

Script di prova:

(   
  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 del Master A (B è uno schiavo di A)
  • Esegui l'aggiornamento dello schema su Master B. Rimarrà indietro durante l'aggiornamento
  • Lascia che il Maestro B ti raggiunga. Invariante:la modifica dello schema DEVE essere in grado di elaborare i comandi replicati da uno schema di 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 (fidati di me, lo fai), dovresti assicurarti che l'ultima scrittura su A sia replicata su B PRIMA B esegue la prima scrittura. Se consenti scritture simultanee a più di 2 master, ... capisci meglio la replica di MySQL a un livello DEEP o sei diretto verso un mondo di dolore. Dolore estremo. Ad esempio, hai una colonna che è AUTOINCREMENTO??? sei fregato (a meno che tu non usi numeri pari su un master e quote 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 manualmente. Tuttavia, la disconnessione di tutti i client dal vecchio master e il loro passaggio al nuovo master possono essere eseguiti in pochi secondi, molto più rapidamente rispetto all'attesa di 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 potere o si muova addosso a te.
  • li>

Un modo semplice per aggiornare lo schema non lo è. Funzionabile 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, fammi sapere.

Google mi ha portato a questo articolo che descrive una tecnica simile. Ancora meglio, consigliano di bere nello stesso punto della procedura (si noti che ho scritto la mia risposta prima di leggere l'articolo)!

Modifica dello schema pt-online di Percona

L'articolo Ho collegato sopra parla di uno strumento, pt -cambio-schema-online , che funziona come segue:

  • Crea una nuova tabella con la stessa struttura dell'originale.
  • Aggiorna lo schema su una nuova tabella.
  • Aggiungi un attivatore sulla tabella originale in modo che le modifiche siano sincronizzate con la copia
  • Copia righe in batch dalla tabella originale.
  • Sposta la tabella originale e sostituiscila con una nuova.
  • Annulla 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 racchiude e gestisce MySQL, consentendoti di aggiungere nuove repliche di lettura con un solo pulsante e aggiornare in modo trasparente il database attraverso SKU hardware. È davvero conveniente. Non ottieni SUPER accesso al database, quindi non puoi rovinare direttamente la replica (è una benedizione o una maledizione?). Tuttavia, puoi utilizzare Leggi la promozione della replica per apportare le modifiche allo schema su uno slave di sola lettura, quindi promuovi quello slave in modo che diventi il ​​tuo 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.