Lo scopo di questo articolo è, attraverso la libreria mostrare gli strumenti che possono semplificare notevolmente il processo di sviluppo di database all'interno di progetti PHP che utilizzano il DBMS PostgreSQL.
Le informazioni contenute in questo articolo saranno particolarmente utili ai programmatori che desiderano sfruttare al meglio le potenzialità di PostgreSQL, ma si trovano di fronte a problemi di manutenzione della logica di business trasferita nel database.
L'articolo non tratterà i vantaggi o gli svantaggi di memorizzare la logica di business nel database. Si presuppone che la scelta sia già stata effettuata dal lettore.
Saranno affrontate le seguenti questioni:
- In quale formato memorizzare il dump della struttura del database nel sistema di controllo versione (d'ora in poi - VCS)
- Come monitorare le modifiche alla struttura del database dopo aver salvato il dump
- Come trasferire le modifiche alla struttura del database su altri ambienti senza conflitti e migrazioni di grandi dimensioni
- Come organizzare il lavoro parallelo di più sviluppatori su un progetto
- Come implementare in sicurezza un numero maggiore di modifiche alla struttura del database nell'ambiente di produzione
SchemaKeeper è progettato per lavorare con procedure memorizzate scritte nel linguaggio . Non sono stati condotti test con altre lingue, quindi l'uso potrebbe non essere altrettanto efficace o addirittura impossibile.
In quale forma conservare il dump della struttura del DB in VCS
Libreria fornisce la funzione saveDump, che salva la struttura di tutti gli oggetti del DB come singoli file di testo. In uscita viene creata una directory contenente la struttura del DB suddivisa in file raggruppati, facilmente aggiungibili al VCS.
Consideriamo la trasformazione degli oggetti del DB in file in diversi 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
Vista
booking
tariffs
./booking/views/tariffs.txt
Il contenuto dei file è una rappresentazione testuale della struttura di un oggetto specifico del DB. 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, schema e nome dell'oggetto. Questo approccio facilita la navigazione nel dump e la revisione del codice delle modifiche nel DB.
Espansione
.sqlper i file con il codice sorgente delle procedure archiviate, è 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 nel VCS, otteniamo la possibilità di verificare se sono state apportate modifiche alla struttura del database dopo la creazione del dump. Nella libreria per identificare le modifiche nella struttura del database è prevista la funzione verifyDump, che restituisce informazioni sulle differenze senza effetti collaterali.
Un metodo alternativo di controllo consiste nel richiamare nuovamente la funzione saveDump, specificando la stessa directory e verificando nel VCS la presenza di modifiche. Poiché tutti gli oggetti del database sono salvati in file separati, il VCS mostrerà solo gli oggetti modificati.
Il principale svantaggio di questo metodo è la necessità di riscrivere i file per vedere le modifiche.
Come trasferire le modifiche alla struttura del database su altri ambienti senza conflitti e migrazioni di grandi dimensioni
Grazie alla funzione deployDump Il codice sorgente delle stored procedure può essere modificato esattamente come il codice sorgente di un'applicazione normale. È possibile aggiungere o rimuovere nuove righe nel codice delle stored procedure e inviare immediatamente le modifiche nel sistema di controllo versione, oppure creare o eliminare stored procedure creando o eliminando i relativi file nella directory di backup.
Ad esempio, per creare una nuova stored procedure nello schema pubblico è sufficiente creare un nuovo file con estensione .sql nella directory public/functions, inserire il codice sorgente della stored procedure, incluso il blocco CREATE OR REPLACE FUNCTION, e poi chiamare la funzione deployDump. Lo stesso vale per la modifica e la rimozione di una stored procedure. In questo modo, il codice finisce sia nel VCS che nel database.
Se nel codice sorgente di una qualsiasi stored procedure si verifica un errore, o c'è una discrepanza tra il nome del file e la stored procedure, allora deployDump non verrà eseguita, mostrando il messaggio di errore. La discrepanza tra le stored procedure nel dump e l'attuale DB non è possibile utilizzando deployDump.
Quando si crea una nuova stored procedure, non è necessario immettere manualmente il nome corretto del file. È sufficiente che il file abbia l'estensione
.sql. Dopo la chiamatadeployDumpil messaggio di errore conterrà il nome corretto che può essere utilizzato per rinominare il file.
deployDump permette di modificare i parametri di funzione o il tipo di ritorno senza ulteriori azioni, mentre con l'approccio classico sarebbe stato necessario
eseguire prima DROP FUNCTION, e solo dopo CREATE OR REPLACE FUNCTION.
Sfortunatamente, ci sono alcune situazioni in cui deployDump non è possibile applicare automaticamente le modifiche. Ad esempio, se si elimina una funzione di trigger utilizzata da almeno un trigger. Tali situazioni devono essere risolte manualmente utilizzando file di migrazione.
Se il trasferimento delle modifiche nelle procedure memorizzate è gestito dallo stesso , per trasferire le altre modifiche nella struttura è necessario utilizzare file di migrazione. Ad esempio, una buona libreria per la gestione delle migrazioni è .
Le migrazioni devono essere applicate prima di avviare deployDump. Questo consente di apportare tutte le modifiche alla struttura e risolvere situazioni problematiche affinché le modifiche nelle procedure memorizzate siano trasferite senza problemi in seguito.
Lavorare con le migrazioni sarà descritto più dettagliatamente nei capitoli successivi.
Come organizzare il lavoro parallelo di più sviluppatori su un progetto
È necessario creare uno script per l'inizializzazione completa del database che verrà eseguito dallo sviluppatore sulla propria macchina, allineando la struttura del database locale a quella del dump salvato nel VCS. È più semplice dividere l'inizializzazione del database locale in 3 fasi:
- Importazione di un file con la struttura di base, che si chiamerà, ad esempio,
base.sql - Applicazione delle migrazioni
- La chiamata
deployDump
base.sqlè il punto di partenza, sopra il quale vengono applicate le migrazioni e viene eseguitodeployDump, vale a direbase.sql + migrazioni + deployDump = struttura attuale del database. È possibile generare un tale file utilizzando l'utilitypg_dump. Viene utilizzatobase.sqlesclusivamente per l'inizializzazione del database da zero.
Chiamiamo lo script per l'inizializzazione completa del database refresh.sh. Il flusso di lavoro potrebbe 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 in base alle esigenze della nuova funzionalità (
ALTER TABLE ... ADD COLUMNecc.) - Dopo aver completato il compito, lo sviluppatore chiama la funzione
saveDump, per registrare nel VCS le modifiche apportate al database - Lo sviluppatore esegue nuovamente
refresh.sh, poiverifyDump, che ora mostra l'elenco delle modifiche da includere nella migrazione - Lo sviluppatore trasferisce tutte le modifiche della struttura nel file di migrazione e lo 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 avverrà la fusione dei dump. Nella maggior parte dei casi, dopo la fusione non è necessario intraprendere ulteriori azioni, ma se in branch diversi sono state apportate modifiche, ad esempio, alla 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 presentano conflitti con develop, ma hanno conflitti tra di loro. L'obiettivo è eseguire la fusione di entrambi i branch in develop. Per questo caso, è consigliabile prima eseguire la fusione di uno dei branch in develop, e poi la fusione di develop nell'altro branch, risolvendo i conflitti in quest'ultimo, dopodiché eseguire la fusione dell'ultimo branch in develop. Nella fase di risoluzione dei conflitti potrebbe essere necessario modificare il file di migrazione nell'ultima branch affinché corrisponda al dump finale, includendo i risultati delle fusioni.
Come implementare in sicurezza un numero maggiore di modifiche alla struttura del database nell'ambiente di produzione
Grazie alla presenza nel VCS di un dump della struttura attuale del database, è possibile verificare che il database di produzione corrisponda esattamente alla struttura richiesta. Questo garantisce che tutte le modifiche pensate dagli sviluppatori siano state trasferite con successo nel database di produzione.
Poiché in PostgreSQL è , si raccomanda di seguire il seguente ordine di deployment, affinché, in caso di errore imprevisto, si possa eseguire un'operazione "indolore". ROLLBACK:
- Iniziare la transazione
- Eseguire tutte le migrazioni nella transazione
- Nella stessa transazione eseguire
deployDump - Senza terminare la transazione, eseguire
verifyDump. Se non ci sono errori, eseguireCOMMIT. Se ci sono errori, eseguireROLLBACK
Questi passaggi si integrano facilmente con gli approcci esistenti per il deployment delle applicazioni, incluso il zero-downtime.
Conclusione
Grazie ai metodi sopra descritti, è possibile massimizzare le prestazioni dei progetti "PHP + PostgreSQL", sacrificando una quantità relativamente modesta di comodità nello sviluppo rispetto all'implementazione dell'intera 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
