L'obiettivo di questo articolo è illustrare, attraverso la libreria , gli strumenti che consentono di semplificare notevolmente il processo di sviluppo di database all'interno di progetti PHP che utilizzano il DBMS PostgreSQL.
Le informazioni di questo articolo saranno utili in primo luogo agli sviluppatori che desiderano sfruttare al massimo le potenzialità di PostgreSQL, ma che si trovano ad affrontare problemi di manutenzione della logica aziendale spostata nel database.
L'articolo non descriverà i vantaggi o gli svantaggi di conservare la logica aziendale nel database. Si presume che la scelta sia già stata fatta dal lettore.
Saranno esaminati i seguenti punti:
- In quale formato conservare il dump della struttura del database nel sistema di controllo versione (di seguito VCS)
- Come monitorare le modifiche alla struttura del database dopo aver salvato il dump
- Come trasferire le modifiche alla struttura del database in altri ambienti senza conflitti e senza giganteschi file di migrazione
- Come organizzare il lavoro parallelo su un progetto da parte di più sviluppatori
- Come implementare in modo sicuro un numero maggiore di modifiche alla struttura del database nell'ambiente di produzione
SchemaKeeper è progettato per lavorare con procedure memorizzate scritte nel linguaggio . I test con altri linguaggi non sono stati effettuati, pertanto l'uso potrebbe non essere altrettanto efficace o potrebbe essere impossibile.
In quale formato conservare il dump della struttura del database nel VCS
La libreria fornisce la funzione saveDump, che salva la struttura di tutti gli oggetti dal database come singoli file di testo. In output viene creata una directory contenente la struttura del database, suddivisa in file raggruppati, che possono essere facilmente aggiunti al VCS.
Esaminiamo la trasformazione degli oggetti dal database in file con alcuni esempi:
Tipo di oggetto
Schema
Nome
Percorso relativo al file
Tabella
pubblico
accounts
./public/tables/accounts.txt
Procedura memorizzata
pubblico
auth(hash bigint)
./public/functions/auth(int8).sql
Rappresentazione
booking
tariffs
./booking/views/tariffs.txt
Il contenuto dei file è una rappresentazione testuale della struttura di un particolare oggetto del database. Ad esempio, per le procedure memorizzate, il contenuto del file sarà la definizione completa della procedura memorizzata, che inizia con il blocco CREATE OR REPLACE FUNCTION.
Come si può vedere dalla tabella sopra, il percorso del file contiene informazioni sul tipo, sullo schema e sul nome dell'oggetto. Questo approccio facilita la navigazione nel dump e la revisione del codice delle modifiche nel database.
Estensione
.sqlper i file con codice sorgente delle procedure memorizzate, è stato scelto affinché l'IDE fornisca automaticamente gli strumenti per interagire con il database all'apertura del file.
Come monitorare le modifiche alla struttura del database dopo aver salvato il dump
Salvando il dump della struttura attuale del database in VCS, otteniamo la possibilità di verificare se sono state apportate modifiche alla struttura del database dopo la creazione del dump. Nella libreria è prevista una funzione per rilevare le modifiche nella struttura del database verifyDump, che restituisce informazioni sulle differenze senza effetti collaterali.
Un modo alternativo per controllare è richiamare nuovamente la funzione saveDump, specificando la stessa directory, e controllare in VCS la presenza di modifiche. Poiché tutti gli oggetti del database sono salvati in file separati, VCS mostrerà solo gli oggetti modificati.
Il principale svantaggio di questo metodo è la necessità di sovrascrivere i file per visualizzare le modifiche.
Come trasferire le modifiche alla struttura del database in altri ambienti senza conflitti e senza giganteschi file di migrazione
Grazie alla funzione deployDump , il codice sorgente delle procedure memorizzate può essere modificato esattamente come il codice sorgente dell'applicazione. È possibile aggiungere/rimuovere nuove righe nel codice delle procedure memorizzate e inviare immediatamente le modifiche nel sistema di controllo versione, oppure creare/rimuovere procedure memorizzate creando/rimuovendo i corrispondenti file nella directory del dump.
Ad esempio, per creare una nuova procedura memorizzata nello schema pubblico , è sufficiente creare un nuovo file con estensione .sql nella directory public/functions, inserire il codice sorgente della procedura memorizzata, incluso il blocco CREATE OR REPLACE FUNCTION, e poi richiamare la funzione deployDump. Allo stesso modo avviene la modifica e la rimozione della procedura memorizzata. In questo modo, il codice entra sia in VCS che nel database.
Se nel codice sorgente di una qualsiasi procedura memorizzata si verifica un errore, oppure un'incongruenza tra il nome del file e la procedura memorizzata, allora deployDump non verrà eseguita, mostrando il testo dell'errore. La discordanza delle procedure memorizzate tra il dump e il database attuale è impossibile utilizzando deployDump.
Quando si crea una nuova procedura memorizzata, non è necessario immettere manualmente il nome corretto del file. È sufficiente che il file abbia l'estensione
.sql. Dopo la chiamata,deployDumpil testo dell'errore conterrà il nome corretto che può essere utilizzato per rinominare il file.
deployDump permette di modificare i parametri della funzione o il tipo di ritorno senza ulteriori azioni, mentre nell'approccio classico sarebbe stato necessario
eseguire prima DROP FUNCTION, e solo dopo CREATE OR REPLACE FUNCTION.
Purtroppo, ci sono alcune situazioni in cui deployDump non è possibile applicare automaticamente le modifiche. Ad esempio, se viene rimossa una funzione di trigger utilizzata da almeno un trigger. Queste situazioni devono essere gestite manualmente utilizzando i file di migrazione.
Se il trasferimento delle modifiche nelle procedure memorizzate è responsabilità dello , per trasferire le altre modifiche nella struttura è necessario utilizzare i file di migrazione. Ad esempio, una buona libreria per lavorare con le migrazioni è .
Le migrazioni devono essere applicate prima dell'avvio deployDump. Questo consente di apportare tutte le modifiche alla struttura e risolvere le situazioni problematiche, affinché le modifiche nelle procedure memorizzate possano successivamente essere trasferite senza problemi.
Un'analisi più dettagliata del lavoro con le migrazioni sarà fornita nei capitoli successivi.
Come organizzare il lavoro parallelo su un progetto da parte di più sviluppatori
È necessario creare uno script per l'inizializzazione completa del database, che sarà eseguito dallo sviluppatore sulla propria macchina di lavoro, allineando la struttura del database locale a quella salvata nel dump VCS. La cosa più semplice è suddividere l'inizializzazione del database locale in 3 passaggi:
- Importazione di un file con la struttura di base, che si chiamerà, ad esempio,
base.sql - Applicazione delle migrazioni
- Chiamata
deployDump
base.sqlè il punto di partenza, su cui vengono applicate le migrazioni e viene eseguitodeployDump, cioèbase.sql + migrazioni + deployDump = struttura attuale del database. Un file di questo tipo può essere generato con il supporto di un'utilità.pg_dumpUtilizzatobase.sqlesclusivamente durante l'inizializzazione del database da zero.
Chiameremo lo script per l'inizializzazione completa del database refresh.sh. Il processo di lavoro può apparire come segue:
- Lo sviluppatore esegue nel proprio ambiente
refresh.she ottiene la struttura attuale del database - Lo sviluppatore inizia a lavorare sul compito assegnato, modificando il database locale per soddisfare le esigenze della nuova funzionalità (
ALTER TABLE ... ADD COLUMNecc.) - Dopo aver completato il compito, lo sviluppatore chiama la funzione
saveDump, per registrare in VCS le modifiche apportate al database - Lo sviluppatore esegue nuovamente
refresh.sh, quindiverifyDump, che ora mostra l'elenco delle modifiche da includere nella migrazione - Lo sviluppatore trasferisce tutte le modifiche della struttura nel file di migrazione, esegue di nuovo
refresh.sheverifyDump, e, se la migrazione è stata compilata correttamente,verifyDumpmostrerà l'assenza di differenze tra il database locale e il dump salvato
Il processo descritto sopra è compatibile con i principi di gitflow. Ogni branch nel VCS conterrà la propria versione del dump, e durante la fusione dei branch si verificherà una fusione dei dump. Nella maggior parte dei casi, dopo la fusione non è necessario intraprendere ulteriori azioni, ma se sono state apportate modifiche in branch diversi, ad esempio nella stessa tabella, potrebbe sorgere un conflitto.
Consideriamo una situazione di conflitto, ad esempio: c'è un branch develop., da cui si diramano due branch: feature1 e feature2, che non hanno conflitti con develop., ma hanno conflitti tra di loro. È necessario effettuare la fusione di entrambi i branch in develop.. In questo caso, è consigliabile prima eseguire la fusione di uno dei branch in develop., e poi effettuare la fusione develop. nell'altro branch, risolvendo i conflitti in quest'ultimo branch, dopodiché eseguire la fusione dell'ultimo branch in develop.. Durante la fase di risoluzione dei conflitti, potrebbe essere necessario correggere il file di migrazione nell'ultimo branch per farlo corrispondere al dump finale, che include i risultati delle fusioni.
Come implementare in modo sicuro un numero maggiore di modifiche alla struttura del database nell'ambiente di produzione
Grazie alla disponibilità nel VCS di un dump della struttura attuale del database, diventa possibile verificare il database di produzione per la corrispondenza esatta con la struttura richiesta. Questo garantisce che tutte le modifiche previste dagli sviluppatori siano state trasferite con successo nel database di produzione.
Poiché in PostgreSQL è , si raccomanda di seguire il seguente ordine di deployment, in modo che, in caso di errore imprevisto, si possa eseguire senza problemi ROLLBACK:
- Iniziare la transazione
- Eseguire tutte le migrazioni nella transazione
- Nella stessa transazione eseguire
deployDump - Senza chiudere la transazione, eseguire
verifyDump. Se non ci sono errori, eseguireCOMMIT. Se ci sono errori, eseguireROLLBACK
Questi passaggi si integrano abbastanza facilmente nei metodi esistenti per il deployment delle applicazioni, inclusi quelli a zero downtime.
Conclusione
Grazie ai metodi descritti sopra, è possibile ottenere il massimo dalle performance dei progetti "PHP + PostgreSQL", sacrificando però relativamente poca comodità nello sviluppo rispetto all'implementazione di tutta la logica di business nel codice principale dell'applicazione. Inoltre, l'elaborazione dei dati in spesso appare più trasparente e richiede meno codice rispetto alla stessa funzionalità scritta in PHP.
Fonte: habr.com
