Logica aziendale nel database utilizzando SchemaKeeper

Lo scopo di questo articolo è utilizzare l'esempio di una libreria custode dello schema mostrare strumenti che possono semplificare in modo significativo il processo di sviluppo di database all'interno di progetti PHP utilizzando il DBMS PostgreSQL.

Le informazioni contenute in questo articolo saranno innanzitutto utili agli sviluppatori che desiderano sfruttare al massimo le funzionalità di PostgreSQL, ma si trovano ad affrontare problemi nel mantenimento della logica aziendale inserita nel database.

Questo articolo non descriverà i vantaggi o gli svantaggi dell'archiviazione della logica aziendale in un database. Si presuppone che la scelta sia già stata fatta dal lettore.

Verranno prese in considerazione le seguenti domande:

  1. In quale forma il dump della struttura del database dovrebbe essere archiviato in un sistema di controllo della versione (di seguito denominato VCS)
  2. Come tenere traccia delle modifiche nella struttura del database dopo aver salvato un dump
  3. Come trasferire le modifiche nella struttura del database ad altri ambienti senza conflitti e file di migrazione giganteschi
  4. Come organizzare il processo di lavoro parallelo su un progetto da parte di più sviluppatori
  5. Come distribuire in modo sicuro più modifiche nella struttura del database in un ambiente di produzione

    SchemaKeeper progettato per lavorare con procedure memorizzate scritte nel linguaggio PL / pgSQL. Non sono stati effettuati test con altre lingue, quindi l'utilizzo potrebbe non essere altrettanto efficace o non essere possibile.

Come archiviare un dump della struttura del database in VCS

Biblioteca custode dello schema fornisce una funzione saveDump, che salva la struttura di tutti gli oggetti dal database come file di testo separati. L'output è una directory contenente la struttura del database, divisa in file raggruppati che possono essere facilmente aggiunti a VCS.

Diamo un'occhiata alla conversione di oggetti da un database in file utilizzando diversi esempi:

Tipo di oggetto
Guida
Nome
Percorso relativo al file

tavolo
la percezione
conti
./public/tables/accounts.txt

Procedura memorizzata
la percezione
autenticazione(hash bigint)
./public/functions/auth(int8).sql

idea
riunioni
tariffe
./booking/views/tariffs.txt

Il contenuto dei file è una rappresentazione testuale della struttura di uno specifico oggetto di database. Ad esempio, per le procedure memorizzate, il contenuto del file sarà la definizione completa della procedura memorizzata, a partire dal blocco CREATE OR REPLACE FUNCTION.

Come si può vedere dalla tabella sopra, il percorso del file memorizza informazioni sul tipo, lo schema e il nome dell'oggetto. Questo approccio semplifica la navigazione attraverso il dump e la revisione del codice delle modifiche nel database.

estensione .sql per i file con codice sorgente di procedura memorizzata, questo è stato selezionato in modo che l'IDE fornisca automaticamente gli strumenti per interagire con il database quando il file viene aperto.

Come tenere traccia delle modifiche nella struttura del database dopo aver salvato un dump

Salvando un dump della struttura del database corrente in VCS, abbiamo l'opportunità di verificare se sono state apportate modifiche alla struttura del database dopo la creazione del dump. In biblioteca custode dello schema per rilevare i cambiamenti nella struttura del database, viene fornita una funzione verifyDump, che restituisce informazioni sulle differenze senza effetti collaterali.

Un modo alternativo per verificare è richiamare nuovamente la funzione saveDump, specificando la stessa directory e controlla le modifiche in VCS. Poiché tutti gli oggetti del database vengono salvati in file separati, VCS mostrerà solo gli oggetti modificati.
Lo svantaggio principale di questo metodo è la necessità di sovrascrivere i file per poter vedere le modifiche.

Come trasferire le modifiche nella struttura del database ad altri ambienti senza conflitti e file di migrazione giganteschi

Grazie alla funzione deployDump Il codice sorgente delle procedure memorizzate può essere modificato esattamente nello stesso modo del normale codice sorgente dell'applicazione. È possibile aggiungere/eliminare nuove righe nel codice della procedura memorizzata e inviare immediatamente le modifiche al controllo della versione oppure creare/eliminare procedure memorizzate creando/eliminando i file corrispondenti nella directory dump.

Ad esempio, per creare una nuova procedura memorizzata in uno schema public basta creare un nuovo file con l'estensione .sql nella rubrica public/functions, inserire al suo interno il codice sorgente della procedura memorizzata, incluso il blocco CREATE OR REPLACE FUNCTION, quindi richiama la funzione deployDump. La modifica e l'eliminazione di una procedura memorizzata avvengono allo stesso modo. Pertanto, il codice entra contemporaneamente sia nel VCS che nel database.

Se viene visualizzato un errore nel codice sorgente di qualsiasi procedura memorizzata o una discrepanza tra i nomi del file e la procedura memorizzata, allora deployDump fallirà, visualizzando il testo dell'errore. La mancata corrispondenza delle procedure memorizzate tra il dump e il database corrente è impossibile durante l'utilizzo deployDump.

Quando si crea una nuova procedura memorizzata, non è necessario immettere manualmente il nome file corretto. È sufficiente che il file abbia l'estensione .sql. Dopo la chiamata deployDump il testo dell'errore conterrà il nome corretto, che potrà essere utilizzato per rinominare il file.

deployDump ti consente di modificare i parametri di una funzione o il tipo restituito senza azioni aggiuntive, mentre con l'approccio classico dovresti farlo
eseguire prima DROP FUNCTION, e solo allora CREATE OR REPLACE FUNCTION.

Sfortunatamente, ci sono alcune situazioni in cui deployDump impossibile applicare automaticamente le modifiche. Ad esempio, se viene rimossa una funzione trigger utilizzata da almeno un trigger. Tali situazioni vengono risolte manualmente utilizzando i file di migrazione.

Se sei responsabile della migrazione delle modifiche alle procedure archiviate custode dello schema, i file di migrazione devono essere utilizzati per trasferire altre modifiche nella struttura. Ad esempio, una buona libreria per lavorare con le migrazioni è dottrina/migrazioni.

Le migrazioni devono essere applicate prima del lancio deployDump. Ciò consente di apportare tutte le modifiche alla struttura e risolvere situazioni problematiche in modo che le modifiche alle stored procedure vengano successivamente trasferite senza problemi.

L'utilizzo delle migrazioni verrà descritto in modo più dettagliato nelle sezioni seguenti.

Come organizzare il processo di lavoro parallelo su un progetto da parte di più sviluppatori

È necessario creare uno script per l'inizializzazione completa del database, che verrà lanciato dallo sviluppatore sulla propria macchina da lavoro, adeguando la struttura del database locale al dump memorizzato in VCS. Il modo più semplice è dividere l'inizializzazione del database locale in 3 passaggi:

  1. Importa un file con una struttura base che si chiamerà ad es. base.sql
  2. Applicazione delle migrazioni
  3. chiamata deployDump

base.sql è il punto di partenza sul quale vengono applicate ed eseguite le migrazioni deployDumpCioè, base.sql + миграции + deployDump = актуальная структура БД. È possibile creare un file di questo tipo utilizzando l'utilità pg_dump. Usato base.sql esclusivamente durante l'inizializzazione del database da zero.

Chiamiamo lo script per l'inizializzazione completa del database refresh.sh. Il flusso di lavoro potrebbe assomigliare a questo:

  1. Lo sviluppatore si avvia nel suo ambiente refresh.sh e ottiene la struttura corrente del database
  2. Lo sviluppatore inizia a lavorare sull'attività da svolgere, modificando il database locale per soddisfare le esigenze della nuova funzionalità (ALTER TABLE ... ADD COLUMN e così via)
  3. Dopo aver completato l'attività, lo sviluppatore chiama la funzione saveDumpper confermare le modifiche apportate al database in VCS
  4. Rilancio degli sviluppatori refresh.sh, lo giuro verifyDumpche ora mostra un elenco di modifiche da includere nella migrazione
  5. Lo sviluppatore trasferisce tutte le modifiche alla struttura nel file di migrazione e viene eseguito di nuovo refresh.sh и verifyDumpe, se la migrazione è stata compilata correttamente, verifyDump non mostrerà differenze tra il database locale e il dump salvato

Il processo sopra descritto è compatibile con i principi di gitflow. Ogni ramo nel VCS conterrà la propria versione del dump e, quando si uniscono i rami, i dump verranno uniti. Nella maggior parte dei casi, dopo l'unione non è necessario intraprendere alcuna azione aggiuntiva, ma se vengono apportate modifiche in rami diversi, ad esempio nella stessa tabella, potrebbe verificarsi un conflitto.

Consideriamo una situazione di conflitto usando un esempio: c'è un ramo sviluppare, da cui si dipartono due rami: feature1 и feature2, con cui non hanno conflitti sviluppare, ma sono in conflitto tra loro. Il compito è unire entrambi i rami sviluppare. In questo caso, si consiglia di unire prima uno dei rami in svilupparee poi unire sviluppare al ramo rimanente, risolvendo i conflitti nel ramo rimanente e quindi unendo l'ultimo ramo in sviluppare. Durante la fase di risoluzione del conflitto, potresti dover correggere il file di migrazione nell'ultimo ramo in modo che corrisponda al dump finale, che include i risultati delle unioni.

Come distribuire in modo sicuro più modifiche nella struttura del database in un ambiente di produzione

Grazie alla presenza di un dump della struttura attuale del database in VCS, diventa possibile verificare l'esatto rispetto del database di produzione con la struttura richiesta. Ciò garantisce che tutte le modifiche previste dagli sviluppatori siano state trasferite con successo alla base di produzione.

Come DDL in PostgreSQL è transazionale, si consiglia di attenersi al seguente ordine di distribuzione, in modo che, in caso di errore imprevisto, sia possibile eseguire “indolore” ROLLBACK:

  1. Inizia la transazione
  2. Esegui tutte le migrazioni in una transazione
  3. Nella stessa transazione, esegui deployDump
  4. Senza completare la transazione, esegui verifyDump. Se non ci sono errori, esegui COMMIT. Se ci sono errori, esegui ROLLBACK

Questi passaggi possono essere facilmente integrati negli approcci esistenti alla distribuzione delle applicazioni, compresi i tempi di inattività pari a zero.

conclusione

Grazie ai metodi sopra descritti, è possibile ottenere le massime prestazioni dai progetti "PHP + PostgreSQL", sacrificando relativamente poca comodità di sviluppo rispetto all'implementazione di tutta la logica di business nel codice dell'applicazione principale. Inoltre, il trattamento dei dati in PL / pgSQL spesso sembra più trasparente e richiede meno codice rispetto alla stessa funzionalità scritta in PHP.

Fonte: habr.com

Aggiungi un commento