Rotaie: il modo migliore per apportare modifiche a un database di produzione
-
03-07-2019 - |
Domanda
Devo apportare modifiche a un database di produzione in uso. Aggiungo solo alcune colonne. Ho apportato le modifiche al database degli sviluppatori con le migrazioni. Qual è il modo migliore per aggiornare il database di produzione preservando i dati esistenti e senza interrompere troppo l'operazione?
È MYSQL e avrò bisogno di aggiungere dati alle colonne anche per i record già esistenti. Una colonna può avere un valore predefinito (è booleano) ma l'altra è un timestamp e dovrebbe avere un valore retrodatato arbitrario. I conteggi delle righe non sono enormi.
Quindi, se uso le migrazioni come faccio ad aggiungere dati e come ottengo che facciano solo le due (o tre - aggiungo le migrazioni più recenti sul db di produzione quando non è stato inizialmente creato tramite le migrazioni (credo hanno usato lo schema invece)?
Soluzione
Sembra che tu sia in uno stato in cui lo schema db di produzione non corrisponde esattamente a quello che stai usando in dev (anche se non è del tutto chiaro). Vorrei tracciare una linea nella sabbia e ottenere quel prodotto in uno stato migliore. In sostanza, quello che vuoi fare è assicurarti che il db del prodotto abbia un & Quot; schema_info & Quot; tabella che elenca tutte le migrazioni che > non < mai voluto correre in produzione. Quindi puoi aggiungere migrazioni al contenuto del tuo cuore e funzioneranno contro il db di produzione.
Una volta fatto che puoi scrivere le migrazioni che aggiungono modifiche allo schema o aggiungono dati, ma una cosa di cui devi fare molta attenzione è che se aggiungi dati usando una migrazione, devi definire il modello all'interno della migrazione stessa , in questo modo:
class AddSomeColumnsToUserTable < ActiveRecord::Migration
class User < ActiveRecord::Base; end
def self.up
add_column :users, :super_cool, :boolean, :default => :false
u = User.find_by_login('cameron')
u.super_cool = true
u.save
end
def self.down
remove_column :users, :super_cool
end
end
La ragione di ciò è che in futuro potresti rimuovere del tutto il modello, durante un refactoring o altro. Se non si definisce la classe utente sulla riga & Quot; User.find_by_login ... & Quot; la migrazione genererà un'eccezione che è un grande dolore.
Altri suggerimenti
Seguo sempre questa procedura:
- Scarica il database dei prod con il comando mysqldump
- Popolare il database dev / test con dump usando il comando mysql
- Esegui migrazioni in sviluppo / test
- Controlla la migrazione ha funzionato
- Scarica il database prod con il comando mysqldump (come potrebbe essere cambiato) mantenendo il backup sul server
- Esegui migrazioni su prod (usando capristano)
- La migrazione di test ha funzionato su prod
- Bevi birra (mentre guardi i log degli errori)
C'è un motivo per cui non stai usando le stesse migrazioni che hai usato nel tuo ambiente di sviluppo?
L'aggiunta di una colonna con add_column
in una migrazione dovrebbe essere non distruttiva: genererà un " ALTER TABLE " dichiarazione. Se sai cosa inserirai nelle colonne una volta create, puoi inserire i valori all'interno della migrazione (puoi scegliere un'alternativa meno dispendiosa in termini di tempo se i conteggi delle righe sono grandi).
La rimozione o l'alterazione della definizione di una colonna è, credo, dipendente dalla piattaforma: alcuni consentiranno la cancellazione di una colonna in atto, altri eseguiranno una sequenza di comandi rename-create-select-drop.
Per essere più specifici, abbiamo bisogno di maggiori informazioni: che tipo di migrazione stai guardando, su quale piattaforma stai eseguendo, devi impostare i valori come parte della migrazione? Cose del genere sarebbero di grande aiuto: basta modificare la domanda, che la farà risalire all'elenco.