Parte 2: Il nuovo playbook di Jen
Questa serie rivisita la metodologia dell'Evolutionary Database Design, vent'anni dopo. Un vincolo chiave per considerare le modifiche al database come codice è sempre stato legato alla condivisione delle risorse del database. Con il branching copy-on-write in Databricks Lakebase, la creazione in un solo secondo e a zero storage di un branch di un database di produzione su scala terabyte è ora un'operazione O(1), e il vincolo che rendeva la Pratica #4 (ognuno ha la propria istanza di database) solo un'aspirazione è venuto meno. In questa serie, gli autori descrivono cosa cambia quando questo vincolo viene rimosso: non la metodologia, che rimane valida, ma le pratiche che emergono per la prima volta, la governance a livello di team che diventa automatica, l'evoluzione del ruolo del DBA e la nuova capacità che gli agenti condividono con le loro controparti umane.
Jen è la sviluppatrice protagonista di Evolutionary Database Design. In quel saggio ha implementato un refactoring del database, dividendo un campo inventory_code in location_code, batch_number e serial_number, come una normale user story, dimostrando che DBA e sviluppatori possono collaborare, gli schemi possono evolversi a piccoli passi e le migrazioni portano avanti il cambiamento in modo sicuro.
La serie ritrova Jen vent'anni dopo. La metodologia che segue è la stessa che seguiva nel 2003. La novità è la capacità tecnica alla base del suo flusso di lavoro, abilitata dall'architettura lakebase: il branching del database copy-on-write, che rende le pratiche di cui ha letto operativamente reali su scala di produzione. Nelle tre parti di questa serie, seguiamo Jen in tre diversi ambiti: la sua giornata (Parte 1), il suo nuovo playbook (Parte 2) e il suo team (Parte 3).
La Parte 1 ha guidato Jen attraverso una singola funzionalità. Le pratiche che ha seguito sono state descritte nel saggio del 2003 Evolutionary Database Design, ampliate nel libro del 2006 Refactoring Databases e integrate nella pipeline di CI/CD nel libro del 2010 Continuous Delivery (Capitolo 12).
Il saggio del 2003 indicava sette pratiche. Cinque di queste sette hanno presentato limiti nella loro applicazione fino al 2026.
La tecnologia introdotta da Databricks Lakebase rimuove gli ostacoli all'implementazione delle pratiche sopra descritte. Databricks Lakebase è un database Postgres gestito che utilizza lo stesso livello di object storage (il data lake) su cui gira il resto del lakehouse di Databricks. I dati del database risiedono in uno storage condiviso e durevole (essenzialmente bucket S3); il motore Postgres viene eseguito come livello di calcolo separato al di sopra di esso. Calcolo e storage scalano in modo indipendente. Il motore può scalare verso l'alto sotto carico, verso il basso quando il traffico diminuisce e a zero quando è inattivo. Lakebase è integrato con Unity Catalog, consentendo una governance unificata su più ambienti.
Il branching del database copy-on-write è ciò che l'architettura disaccoppiata rende pratico su scala. Un branch crea un nuovo puntatore nello stesso storage condiviso con un marcatore di divergenza. Fino a quando il branch non effettua scritture, condivide tutte le pagine con il database padre. Quando il branch scrive, divergono solo le pagine modificate; il padre rimane intatto. Il branching è un'operazione sui metadati, non richiede la copia dei dati e si completa in circa un secondo, indipendentemente dalle dimensioni del padre. I branch mantengono i dati solo nelle pagine modificate.
Quando il costo tecnico di un branch è disaccoppiato dalle dimensioni dei dati al suo interno, il vincolo alla base della Pratica #4 (ognuno ha la propria istanza di database) viene superato. I branch per singolo sviluppatore, per PR e per esperimento diventano la norma. Il livello di compensazione superiore può essere rimosso. I mock escono dal ciclo di test, sostituiti da un vero Postgres su un branch dedicato per ogni test. L'ambiente di staging condiviso smette di essere l'unico posto in cui testare le modifiche allo schema. I database in-memory alternativi (H2, SQLite) vengono rimossi dal livello di unit test. Non è più necessario il sovraccarico DevOps per creare container basati su Docker per eseguire database locali, e le code di ticket dei DBA per il provisioning si riducono perché i branch sono self-service.
La tecnologia è ciò che abilita l'ottimizzazione della metodologia e realizza l'obiettivo delle pratiche alla base del post originale del 2003.
Il branching del database copy-on-write di Lakebase elimina le limitazioni precedenti sulle pratiche originali e ne abilita altre quattro da approfondire.
Le due pratiche che migliorano maggiormente grazie alle funzionalità offerte da Lakebase sono la n. 4 (ognuno ha la propria istanza di database) e la n. 5 (gli sviluppatori integrano continuamente le modifiche al database). Ora non solo tutti hanno un database, ma è possibile avere ogni PR o ogni branch, o più database per branch, con costi e tempi trascurabili. Il meccanismo può essere automatizzato utilizando due modelli di workflow di GitHub Actions che possono essere predisposti in ogni progetto.
Creazione del branch per PR. pr.yml si attiva su pull_request: [opened, synchronize] e crea ci-pr-<N> creato come fork dal branch di base della PR:
Lo stesso job applica le migrazioni al branch di CI ed esegue la suite di test dell'applicazione su un database Postgres reale. L'esempio completo del workflow è disponibile qui: pr.yml
Diff dello schema pubblicata sulla PR. Lo stesso pr.yml job esegue il dump dello schema di entrambi i branch, formatta la diff e la pubblica come commento alla PR. Questo consente al DBA di effettuare la revisione in modo asincrono come qualsiasi altro revisore del codice (Pratica n. 1, riadattata):
Il DBA, il revisore del codice, il team e qualsiasi agente autore della migrazione vedono lo stesso artefatto sulla PR.
Pulizia dei branch al merge. merge.yml elimina il branch della Pull Request di CI ci-pr-<N> e il branch Lakebase del feature branch collegato nel momento in cui viene eseguito il merge della PR:
L'esempio completo del workflow di merge è disponibile qui: merge.yml Con così tanti branch in circolazione, potrebbe valere la pena avere uno script di pulizia settimanale che rimuova i branch orfani e inutilizzati; un esempio di workflow è disponibile qui: cleanup-orphans.yml. Infine, se il merge avviene in un branch "tiered" (a livelli), ad esempio utilizzato per lo staging o main/production (questo concetto verrà approfondito nella parte 3), il workflow può essere orchestrato per creare un nuovo branch dal livello corrispondente per testare le migrazioni prima di applicare la migrazione finale a qualsiasi ambiente in cui gli utenti sono attivi e aggiungono costantemente dati.
Insieme, questi workflow garantiscono che ogni PR ottenga il proprio database e i branch siano effimeri come proprietà della pipeline, anziché come regole di disciplina degli sviluppatori.
Regola. Il DBA collabora con gli sviluppatori durante l'intero sviluppo della funzionalità, non solo al momento della revisione finale. La collaborazione è asincrona, integrata nella PR, nello stesso modo in cui partecipano gli altri revisori del codice.
Perché questa è diventata un'abitudine duratura? La diff dello schema e i risultati dei test di migrazione vengono inseriti automaticamente in ogni PR (vedi Come viene eseguito il workflow in CI sopra). Il DBA esamina un artefatto concreto in base alle proprie tempistiche. La migrazione è già stata eseguita su un branch di CI con dati reali, quindi il DBA non deve simulare mentalmente la modifica.
Funzionamento:
migrations/, db/, directory dei test dello schema).Anti-pattern. Non includere il DBA nel flusso della PR quando ci sono artefatti effettivi da esaminare.
Il ruolo del DBA acquisisce anche nuove responsabilità nell'amministrazione delle policy e nella governance su scala di team. La Parte 3 tratterà questi aspetti.
Regola. Ogni file SQL, script di migrazione e test dello schema risiede nello stesso repository del codice dell'applicazione. Il diff dello schema e i risultati dei test di migrazione si uniscono al set di artefatti come output al momento della PR.
Perché questa è un'abitudine duratura ora? Il branching aggiunge due nuovi artefatti al set: il diff dello schema per PR e i risultati dei test di migrazione dello schema per PR. Entrambi sono generati dalla CI a partire dallo stato effettivo del branch. Entrambi arrivano nella PR come prova concreta di ciò che è stato modificato e di come si è comportato lo script di migrazione delle modifiche.
Meccanismi:
migrations/, db/migration/, alembic/versions/, dipendente dal framework).Anti-pattern. Generare il diff dello schema al di fuori del flusso della PR (una dashboard separata che il revisore deve aprire). L'artefatto deve risiedere dove avviene la revisione. Poiché le modifiche allo schema sono legate alle modifiche al codice, l'interruzione di questa dipendenza crea problemi a valle per il deployment.
Regola. Nessun ALTER TABLE manuale su qualsiasi ambiente. Ogni modifica dello schema è uno script di migrazione con controllo di versione e sottoposto a check-in. Le migrazioni sono idempotenti.
Perché questa è un'abitudine duratura ora? La regola della migrazione come artefatto è rimasta invariata dal 2003. La novità è la disciplina di scrittura dell'idempotenza. La stessa migrazione viene eseguita su molti branch nel corso di una transizione, quindi deve comportarsi allo stesso modo ogni volta. Una migrazione che fallisce alla riapplicazione è un bug.
Meccanismi:
flyway, liquibase, Knex, Alembic o altri; questi framework tengono traccia di quali migrazioni sono state eseguite e quali no, consentendo al team di applicare un comando come flyway migrate che applica solo le modifiche non ancora applicate (tenendo traccia delle modifiche in una tabella di metadati)Anti-pattern. Una migrazione che dipende dal fatto che lo schema si trovi in uno specifico stato intermedio a causa di modifiche locali apportate nel branch. La migrazione deve applicarsi correttamente a qualsiasi branch padre che includa migrazioni precedenti.
Regola. Ogni sviluppatore, ogni PR, ogni esperimento, ogni esecuzione di test ottiene il proprio branch Lakebase.
Perché questa è un'abitudine duratura ora? Non è più necessario lo sforzo extra per creare container Docker, installare server di database locali, acquisire licenze, popolare database vuoti con schemi esistenti e dati di test. Un semplice comando create-branch Lakebase crea un branch di un database da 1 TB nello stesso secondo di un database da 1 MB. Nessun dato viene copiato al momento della creazione; solo le pagine modificate consumano spazio di archiviazione. Le istanze per sviluppatore, per PR e per esperimento sono ormai la norma.
Meccanismi:
databricks postgres create-branch o il flusso branch-create dell'estensione SCM.pr.yml), distrutti al merge o alla chiusura (merge.yml). Vedi Come viene eseguito il flusso di lavoro nella CI sopra per gli snippet di PR e merge.Anti-pattern. Condividere un database di sviluppo all'interno del team "per comodità". La serializzazione guidata dai conflitti menzionata nella Parte 1 si ripresenta nel momento in cui i branch si fondono.
Dove si estende l'esempio di Jen. Il suo branch per sviluppatore è stato derivato da staging all'inizio della feature. Il branch della CI è stato derivato da staging all'apertura della PR. I suoi branch di esplorazione A/B (Pratica #9) sono stati derivati da staging in parallelo. Quattro branch per una singola feature, tutti in pochi secondi, tutti isolati.
Regola. Ogni PR viene eseguita tramite CI su un nuovo branch Lakebase, con migrazioni applicate e test eseguiti su Postgres reale.
Perché questa è un'abitudine duratura ora? La pipeline di CI ha una disciplina di migrazione dal 2010. La novità è l'isolamento per pipeline: ogni PR ottiene il proprio branch, quindi l'integrazione viene eseguita su dati reali senza conflitti.
Meccanismi:
lakebase-migrate apply.Anti-pattern. Eseguire la validazione della PR su uno staging condiviso. La serializzazione si ripresenta; la proprietà di isolamento per PR va persa.
Regola. Le modifiche allo schema seguono pattern di refactoring specifici: Split Column, Rename Column, Move Column, Replace Type e così via. Ciascuno ha meccanismi di transizione espliciti (mantenere il vecchio e il nuovo in parallelo, popolare dal vecchio, scambiare i lettori, eliminare il vecchio).
Perché questa è un'abitudine duratura ora? Il catalogo del 2006 su databaserefactoring.com elenca oltre 70 refactoring con esempi pratici. La novità nel 2026 è un luogo economico in cui provare i meccanismi di transizione: un branch di sviluppo assorbe la prova; il branch della CI verifica; la produzione vede solo il risultato verificato.
Meccanismi:
Anti-pattern. Una modifica estemporanea dello schema che non corrisponde a un refactoring codificato. Il catalogo di oltre 70 refactoring copre i casi comuni; se ti trovi al di fuori di esso, probabilmente stai combinando più refactoring in un'unica migrazione e dovresti suddividerli.
Dove si estende l'esempio di Jen. La sua migrazione V87 è il refactoring Split Column: la suddivisione di inventory_code in location_code, batch_number e serial_number. La pagina del catalogo su databaserefactoring.com/SplitColumns.html descrive le meccaniche di transizione. Il suo branch era lo spazio di prova; l'esecuzione della CI della PR è stata la verifica.
Regola. Un programmatore può aggiornare lo stato del database del proprio branch on-demand: ripristinare lo stato corrente del parent, creare un fork di un nuovo branch dalla produzione, scartare un branch sperimentale, condividere un branch con un collega. Tutto in pochi secondi.
Perché questa è un'abitudine duratura ora? "On-demand" nel 2026 significa un secondo, in modo isolato, su dati con struttura di produzione. Nessuna di queste operazioni richiede di consultare i calendari delle operazioni o le code dei DBA.
Meccaniche:
databricks postgres create-branch --source production.databricks postgres delete-branch.Anti-pattern. Considerare qualsiasi branch come duraturo oltre il suo scopo. La migrazione è l'artefatto duraturo; il branch è lo spazio di lavoro.
Regola. Quando il raggio d'impatto di un'azione distruttiva è pari a zero, i test distruttivi diventano un'opzione quotidiana anziché un esercizio trimestrale.
Perché questa è un'abitudine duratura ora? Un branch si ripristina in un secondo. Qualsiasi cosa tu faccia a un branch può essere annullata creandone uno nuovo dallo stesso parent. I test distruttivi non hanno più bisogno di calendari delle operazioni e gate di approvazione.
Cose che ora rientrano in un normale ciclo di funzionalità:
Impatto culturale. Quando il ripristino non costa nulla, i team smettono di trattare il database di test come una risorsa preziosa. I test possono essere aggressivi. La pulizia può essere saltata, perché il branch successivo inizia da zero.
Dove si estende l'esempio di Jen. Prima di aprire la sua PR, ha preso i dati con struttura di produzione sul suo branch e ha deliberatamente corrotto circa l'uno percento dei valori di inventory_code per farli sembrare casi limite: cifre mancanti, spazi incorporati, spazi vuoti finali. Il tipo di artefatti che i dati storici accumulano. Ha eseguito la migrazione. Due righe hanno fallito il calcolo della sottostringa. Ha corretto lo script e lo ha eseguito nuovamente. Il branch ha assorbito il test distruttivo. La produzione non l'ha mai visto.
Regola. Quando due progetti sono in competizione, creali su branch paralleli, confrontali con dati con struttura di produzione e mantieni la soluzione migliore.
Perché questa è un'abitudine duratura ora? Il costo per branch è quasi nullo. Esplorare due progetti di schema non richiede più di sceglierne uno in anticipo, né richiede un processo di provisioning che la maggior parte dei team non affronterebbe per una domanda esplorativa.
Meccaniche:
Anti-pattern. Eseguire prototipi A/B senza annotare la decisione e la motivazione. I branch spariscono in un secondo; la decisione di progettazione dovrebbe essere permanente.
Dove si estende l'esempio di Jen. Ha preso in considerazione due progetti per la funzionalità location/batch/serial: tre nuove colonne sulla tabella inventory esistente, o una tabella di lookup inventory_attributes separata con chiave inventory_id, prevedendo che in seguito sarebbero stati aggiunti altri attributi. Ha creato entrambi su branch paralleli a partire da staging. Ha eseguito il percorso di lettura dell'applicazione su ciascuno, ha misurato le prestazioni delle query su dati con struttura di produzione e ha analizzato come ogni migrazione avrebbe scalato sui volumi di produzione. La versione con tabella di lookup ha registrato prestazioni inferiori sul percorso di lettura comune perché ogni visualizzazione dell'inventario richiedeva una join. Ha rilasciato la versione con le colonne, ha eliminato il branch con la tabella di lookup e ha lasciato una nota nella descrizione della PR: Considerata la versione con tabella di lookup; rifiutata perché il percorso di lettura comune diventa una join. Rivalutare se si accumulano più di cinque attributi.
Abbiamo indicato le sette pratiche del 2003 con i limiti che ne hanno mantenuto cinque a livello teorico, le abbiamo riadattate per il 2026 una volta introdotto il branching e abbiamo aggiunto quattro nuove pratiche rese possibili dal branching. In totale, undici pratiche nel nuovo playbook per l'Evolutionary Database Development, 9 delle quali sono spiegate sopra.
Nella Parte 1 – La storia di Jen: una funzionalità, un database abbiamo visto Jen lavorare su una funzionalità: ha associato un branch di codice a un branch Lakebase, ha eseguito una migrazione reale su dati con struttura di produzione in pochi secondi, ha effettuato i test senza mock, ha aperto una PR con il diff dello schema inserito inline e ha completato il merge con la migrazione applicata e i branch effimeri ripuliti. La modifica del database è diventata parte del normale sviluppo.
Nella Parte 3 – Il team di Jen su scala, analizziamo il playbook con cinquanta programmatori, le responsabilità evolute del DBA nell'amministrazione delle policy e nella governance, e gli agenti che creano branch insieme a Jen. Le pratiche n. 10 e n. 11 vengono trattate in modo approfondito in quella sezione.
La Guida: Panoramica del plugin copre l'estensione Lakebase SCM per VS Code e Cursor.
Un Lakebase App Dev Kit per agenti, accompagnato da un e-book per i professionisti umani, sarà rilasciato successivamente.
(Questo post sul blog è stato tradotto utilizzando strumenti basati sull'intelligenza artificiale) Post originale
Iscriviti al nostro blog e ricevi gli ultimi articoli direttamente nella tua casella di posta.