Bene ... eh. Per anni nessuno ha menzionato una cosa sottile.
Nonostante DROP TABLE IF EXISTS `bla`; CREATE TABLE `bla` ( ... );sembri ragionevole, porta a una situazione in cui il vecchio tavolo è già sparito e quello nuovo non è ancora stato creato: alcuni client potrebbero provare ad accedere al tavolo degli argomenti proprio in questo momento.
Il modo migliore è creare una nuova tabella e scambiarla con una vecchia (i contenuti della tabella vanno persi):
CREATE TABLE `bla__new` (id int); /* if not ok: terminate, report error */
RENAME TABLE `bla__new` to `bla`; /* if ok: terminate, report success */
RENAME TABLE `bla` to `bla__old`, `bla__new` to `bla`;
DROP TABLE IF EXISTS `bla__old`;
- Dovresti controllare il risultato
CREATE ...e non continuare in caso di errore , perché fallimento significa che l'altro thread non ha terminato lo stesso script: o perché si è bloccato nel mezzo o semplicemente non è ancora terminato - è una buona idea ispeziona le cose da solo.
- Quindi, dovresti controllare prima il risultato
RENAME ...e non continuare in caso di successo : l'intera operazione è stata completata con successo; ancora di più, l'esecuzione successiva RENAME ...può (e sarà) non sicura se un altro thread ha già avviato la stessa sequenza (è meglio coprire questo caso che non coprire, vedere la nota di blocco di seguito).
- Second
RENAME ...sostituisce atomicamente la definizione della tabella, fare riferimento al
manuale di MySQL
per i dettagli.
- Alla fine,
DROP ...pulisce il vecchio tavolo, ovviamente.
Il wrapping di tutte le istruzioni con qualcosa del genere SELECT GET_LOCK('__upgrade', -1); ... DO RELEASE_LOCK('__upgrade');consente di richiamare tutte le istruzioni in sequenza senza controllo degli errori, ma non credo sia una buona idea: aumenti di complessità e funzioni di blocco in MySQL non sono sicure per la replica basata su istruzioni.
Se i dati della tabella dovessero sopravvivere all'aggiornamento della definizione della tabella ... Per il caso generale è molto più complessa la storia del confronto delle definizioni della tabella per scoprire le differenze e produrre ALTER ...un'istruzione corretta , il che non è sempre possibile automaticamente, ad esempio quando le colonne vengono rinominate.
Nota a margine 1:
è possibile gestire le viste utilizzando lo stesso approccio, in questo caso CREATE/DROP TABLEsi trasforma semplicemente in CREATE/DROP VIEWmentre RENAME TABLErimane invariato. In effetti puoi persino trasformare la tabella in vista e viceversa.
CREATE VIEW `foo__new` as ...; /* if not ok: terminate, report error */
RENAME TABLE `foo__new` to `foo`; /* if ok: terminate, report success */
RENAME TABLE `foo` to `foo__old`, `foo__new` to `foo`;
DROP VIEW IF EXISTS `foo__old`;
Nota a
margine 2: gli utenti di MariaDB dovrebbero essere contenti CREATE OR REPLACE TABLE/VIEW, che si preoccupa già del problema dell'argomento e va bene i punti.