Înapoi la catalog
Season 38 8 Episoade 31 min 2026

Alembic Database Migrations

v1.18 — Ediția 2026. Stăpânește migrările de baze de date cu Alembic 1.18 în Python. Învață cum să gestionezi modificările de schemă, să folosești autogenerate, să manipulezi constrângerile, să scrii scripturi offline și să orchestrezi eficient migrările de baze de date alături de SQLAlchemy.

Baze de date Migrări baze de date ORM
Alembic Database Migrations
Se redă acum
Click play to start
0:00
0:00
1
De ce sunt necesare migrările
Descoperă de ce gestionarea manuală a schemelor eșuează la scară largă și cum Alembic aduce controlul versiunilor în baza ta de date relațională. Explorăm modelul mental de bază al migrărilor de baze de date și descompunem anatomia mediului Alembic.
3m 40s
2
Anatomia unei revizii
Parcurge ciclul de viață al primei tale migrări Alembic. Descompunem funcțiile upgrade și downgrade și dezvăluim cum funcționează cu adevărat urmărirea versiunilor în interiorul bazei de date.
4m 04s
3
Magia și limitele autogenerate
Descoperă cum Alembic detectează automat modificările comparând modelele tale SQLAlchemy cu metadatele bazei de date live. Află ce prinde impecabil și ce îi scapă.
3m 53s
4
Importanța denumirii constrângerilor
Descoperă de ce bazarea pe numele generate de baza de date pentru constrângeri este o rețetă pentru dezastre în migrări. Învață cum să configurezi o convenție de denumire unificată pentru sistemul tău.
3m 53s
5
Migrări offline și generare SQL
Explorează cum să generezi scripturi SQL pure pentru administratorii tăi de baze de date în loc să rulezi Python direct pe baza de date de producție. Discutăm despre fluxul de execuție offline.
4m 31s
6
Migrări batch pentru SQLite
Abordează provocarea modificării tabelelor în SQLite, care nu are suport complet pentru ALTER TABLE. Învață fluxul de lucru move and copy folosind operațiunile batch din Alembic.
4m 00s
7
Lucrul cu branch-uri
Stăpânește colaborarea în echipă gestionând fluxurile de migrare ramificate. Învață cum să identifici și să îmbini istoricele de revizuire divergente atunci când mai mulți dezvoltatori modifică baza de date.
3m 42s
8
Tehnici avansate pentru producție
Treci la nivelul următor cu cunoștințele tale despre Alembic folosind tehnici avansate. Acoperim invocarea programatică a comenzilor și partajarea unei conexiuni cu framework-uri de aplicații precum FastAPI.
3m 57s

Episoade

1

De ce sunt necesare migrările

3m 40s

Descoperă de ce gestionarea manuală a schemelor eșuează la scară largă și cum Alembic aduce controlul versiunilor în baza ta de date relațională. Explorăm modelul mental de bază al migrărilor de baze de date și descompunem anatomia mediului Alembic.

Descarcă
Salut, sunt Alex de la DEV STORIES DOT EU. Migrări de baze de date Alembic, episodul 1 din 8. Rulezi o comandă manuală pe baza de date direct pe serverul de production pentru a adăuga o singură coloană și, dintr-o dată, aplicația se blochează. Codul tău deployat aștepta o anumită structură, baza de date are acum alta și nu există un buton simplu de undo. De aceea, analizăm argumentele pentru migrări. Când un proiect software este la început, modificarea schemei bazei de date este ușoară. Dai drop la tabele și le recreezi. Odată ce ai useri reali și date reale, asta nu mai e o opțiune. Dacă faci modificări manuale în diferite medii, cum ar fi development, staging și production, în cele din urmă vei ajunge la o desincronizare. Codul aplicației tale se bazează pe o stare specifică a bazei de date. Când acea stare deviază, aplicația pică. Alembic rezolvă asta acționând ca un version control pentru schema bazei de date. La fel cum urmărești istoricul codului sursă, Alembic urmărește istoricul structurii bazei de date. Pentru a folosi Alembic, inițializezi un environment de migrare. Asta este o structură de directoare dedicată căreia îi dai commit în repository-ul de source control, alături de codul aplicației. Conține instrucțiunile și configurația necesare pentru a modifica baza de date în timp. Environment-ul este format din trei părți principale. Prima este fișierul de configurare root, numit alembic dot ini. Acest fișier stă la baza proiectului tău. Stochează setările de bază, în principal URL-ul de conectare la baza de date, spunându-i lui Alembic unde se află de fapt baza de date target. Urmează directorul versions. Aici sunt stocate scripturile de migrare. De fiecare dată când trebuie să schimbi schema bazei de date, un nou script Python este creat în acest folder. Fiecare script definește două acțiuni: o funcție de upgrade pentru a aplica modificarea și o funcție de downgrade pentru a-i da revert. Dacă trebuie să adaugi o tabelă pentru profilurile de useri, instrucțiunea exactă pentru acea modificare se află într-un script chiar aici. Ultima piesă este un fișier numit env dot py. E ușor să-l confunzi cu un fișier general de configurare a aplicației sau cu un loc pentru stocarea variabilelor de sistem, dar nu ăsta e scopul lui. Iată ideea principală. Fișierul env dot py face mai exact legătura între modelele aplicației tale și engine-ul de migrare Alembic. Setează engine-ul bazei de date, gestionează lifecycle-ul conexiunii și, cel mai important, încarcă metadata SQLAlchemy. Asta îi spune lui Alembic exact cum arată modelele tale în cod, ca să știe cu ce ar trebui să se potrivească la final schema bazei de date. Ori de câte ori invoci o comandă Alembic, rulează mai întâi acest script env dot py pentru a stabili contextul de care are nevoie ca să funcționeze. În loc să te bazezi pe o memorie fragilă a comenzilor manuale pe baza de date, ai un proces structurat și repetabil. Adevărata valoare a environment-ului Alembic nu este doar că rulează comenzi în siguranță, ci faptul că generează un istoric definitiv, versionat, al modului exact în care structurile tale de date au evoluat din prima zi. Dacă îți place podcastul și vrei să susții emisiunea, ne poți găsi căutând DevStoriesEU pe Patreon. Aș vrea să-ți mulțumesc pentru că ne asculți — ne ajută foarte mult. Să ai o zi faină!
2

Anatomia unei revizii

4m 04s

Parcurge ciclul de viață al primei tale migrări Alembic. Descompunem funcțiile upgrade și downgrade și dezvăluim cum funcționează cu adevărat urmărirea versiunilor în interiorul bazei de date.

Descarcă
Salut, sunt Alex de la DEV STORIES DOT EU. Alembic Database Migrations, episodul 2 din 8. Te-ai întrebat vreodată cum știe de fapt o bază de date ce versiune de schema rulează în prezent? Nu îți inspectează tabelele și nu ghicește pe baza coloanelor care există. Secretul stă într-un singur tabel ascuns, iar înțelegerea modului în care se conectează la codul tău este nucleul din Anatomy of a Revision. Pentru a modifica o schema de bază de date, creezi mai întâi un script de migration. Faci asta rulând comanda Alembic revision împreună cu un scurt mesaj descriptiv, cum ar fi create account table. Alembic generează un nou fișier Python în directorul tău versions. Numele fișierului începe cu un string aleatoriu de caractere, urmat de mesajul tău. Acel string este un GUID parțial, un globally unique identifier. Alembic folosește acești identificatori în loc de numere întregi secvențiale pentru a evita merge conflicts atunci când mai mulți developeri creează migrations pe branches diferite în același timp. Dacă deschizi acel nou fișier Python, vei vedea două variabile în partea de sus: revision și down revision. Variabila revision conține GUID-ul pentru acest script specific. Variabila down revision conține GUID-ul scriptului care a fost imediat înaintea lui. Iată ideea cheie. Developerii cred adesea că aceste migrations sunt aplicate în ordine pe baza timestamp-urilor de creare a fișierelor sau alfabetic, după numele fișierelor. Nu este așa. Alembic se bazează strict pe acel chain de down revision. Citește aceste variabile din fișiere pentru a construi un linked list cu istoricul de schema. Dacă un script nu indică un revision anterior valid, acel chain se rupe. Sub aceste variabile de rutare, vei găsi două funcții goale: upgrade și downgrade. Aici scrii manual modificările de schema. Pentru scenariul nostru, adăugăm un tabel account. În funcția de upgrade, scrii logica pentru a crea tabelul, definindu-ți coloanele, cum ar fi un primary key de tip integer și un string pentru numele contului. Funcția de downgrade trebuie să facă exact opusul. Dacă upgrade creează tabelul account, downgrade trebuie să îi dea drop. Fiecare pas înainte trebuie să aibă un pas înapoi corespunzător și fiabil. Odată ce scriptul tău este scris, îl aplici rulând comanda Alembic upgrade, direcționând-o spre head, ceea ce înseamnă cel mai recent revision din acel chain al tău. Iată ce se întâmplă în culise. Alembic se conectează la baza ta de date și caută un tabel numit alembic version. Dacă asta este prima ta migration, tabelul nu există încă, așa că Alembic îl creează. Acest tabel are exact un rând și o coloană, stocând GUID-ul acelui revision aplicat în prezent. Alembic verifică acest tabel, vede unde se află în prezent baza de date și rulează funcțiile de upgrade ale fiecărui script necesar pentru a ajunge la acel target revision. În cele din urmă, actualizează tabelul version cu noul tău GUID. Dacă testezi noul feature account și realizezi că ceva este în neregulă, poți să îi dai roll back curat. Rulezi comanda Alembic downgrade, pasând un identificator relativ, cum ar fi minus unu, pentru a face un pas înapoi cu un singur revision. Alembic se uită la versiunea curentă din baza de date, găsește scriptul corespunzător și rulează funcția sa de downgrade. Dă drop la tabelul account și actualizează tabelul version cu GUID-ul anterior. Cel mai important aspect este că un script de migration nu este doar o colecție oarecare de comenzi de bază de date. Este un node self-contained într-un linked list care oferă bazei tale de date o cale precisă pentru a se deplasa atât înainte, cât și înapoi în timp. Mulțumesc că ai petrecut câteva minute cu mine. Până data viitoare, toate bune.
3

Magia și limitele autogenerate

3m 53s

Descoperă cum Alembic detectează automat modificările comparând modelele tale SQLAlchemy cu metadatele bazei de date live. Află ce prinde impecabil și ce îi scapă.

Descarcă
Salut, sunt Alex de la DEV STORIES DOT EU. Alembic Database Migrations, episodul 3 din 8. Să ai încredere oarbă într-un tool automat care să-ți scrie database migrations este o cale sigură spre a-ți șterge accidental tabelele din producție. Problema constă în a înțelege ce vede de fapt tool-ul atunci când îți compară codul cu realitatea, și exact asta acoperim astăzi în Magia și limitele funcției de autogenerate. Alembic are un feature de bază numit autogenerate. Când rulezi o comandă de revision cu flag-ul autogenerate, Alembic face o comparație. În primul rând, se conectează la live database și inspectează schema curentă. În al doilea rând, se uită la starea țintă definită de modelele SQLAlchemy din codul aplicației tale. Compară aceste două stări și își dă seama de diferențe. Există o concepție greșită destul de comună despre acest pas. Autogenerate nu aplică magic aceste modificări pe baza ta de date. Pur și simplu scrie un draft de script Python care conține operațiunile de migration pe care le consideră necesare pentru ca baza de date să se potrivească cu modelele tale. Trebuie să faci un review acestui script candidat înainte să-l execuți efectiv pe baza ta de date. Când îți compară baza de date cu modelele, autogenerate detectează cu precizie modificările structurale de bază. Dacă adaugi o nouă clasă de model în codul tău, Alembic face un draft cu o instrucțiune de create table. Dacă ștergi o clasă de model, face un draft cu o instrucțiune de drop table pentru acel tabel. Detectează corect când adaugi sau ștergi coloane, când modifici o coloană ca să permită valori null, sau când adaugi indecși de bază și unique constraints. Pentru aceste operațiuni standard, acest feature te scutește de o cantitate masivă de scris manual. Aici e partea care contează. Autogenerate are unghiuri moarte pentru că nu-ți poate citi gândurile. Să presupunem că decizi să redenumești un tabel existent în modelele tale SQLAlchemy. Actualizezi codul și rulezi comanda de autogenerate, așteptându-te ca Alembic să facă un draft pentru o comandă sigură care să modifice numele tabelului. În schimb, propune ceva extrem de periculos. Face un draft pentru o comandă de drop pe tabelul vechi, distrugând complet toate datele din el, și apoi face un al doilea draft pentru o comandă care să creeze un tabel complet nou cu noul nume. Alembic face asta pentru că vede doar că numele vechi al tabelului există în baza de date, dar lipsește din modelele tale, și că un nume nou de tabel există în modelele tale, dar lipsește din baza de date. Nu are cum să le lege pe cele două printr-un simplu rename. Trebuie să editezi manual scriptul din draft pentru a folosi în schimb o operațiune de rename table. Exact aceeași limitare se aplică și la redenumirea coloanelor. Autogenerate va interpreta o coloană redenumită ca o instrucțiune de drop pentru cea veche și de add pentru una nouă. Dincolo de redenumiri, există modificări pe care autogenerate le va ignora complet by default. Dacă schimbi un data type la o coloană, sau dacă modifici o valoare de server default, Alembic va sări peste aceste diferențe. Poți configura tool-ul să detecteze modificările de tip și de default, dar trebuie să activezi explicit acele setări în environment configuration. Chiar și cu acele setări activate, nu va detecta niciodată modificări la sequence objects sau la numele de constraints. Cel mai sigur mod de a privi autogenerate este ca pe un tool de dictare de mare viteză care se ocupă de boilerplate în locul tău, mai degrabă decât ca pe un sistem inteligent care înțelege intenția din spatele modificărilor tale de cod. Mersi că ai stat cu noi. Sper că ai învățat ceva nou.
4

Importanța denumirii constrângerilor

3m 53s

Descoperă de ce bazarea pe numele generate de baza de date pentru constrângeri este o rețetă pentru dezastre în migrări. Învață cum să configurezi o convenție de denumire unificată pentru sistemul tău.

Descarcă
Salut, sunt Alex de la DEV STORIES DOT EU. Alembic Database Migrations, episodul 4 din 8. Cea mai ușoară metodă să strici un deploy este să încerci să dai drop unei constrângeri din baza de date căreia nu i-ai dat niciodată un nume. Scriptul tău de migration funcționează perfect pe mașina locală, dar mediul de staging tocmai a crăpat, plângându-se de un foreign key lipsă, numit imprevizibil, ceva de genul SYS C 0 0 2 9 3 3 4. Vinovatul este faptul că te bazezi pe identificatori generați de baza de date. Acest episod acoperă importanța denumirii constrângerilor și cum să automatizezi asta. Mulți developeri presupun că object-relational mapper-ul gestionează fără probleme operațiunile de drop pe coloane și pe regulile asociate. Ei definesc un unique constraint sau un foreign key în modelul lor, omit numele ca să salveze timp și merg mai departe. Când faci asta, database engine-ul preia controlul. Sisteme precum Postgres sau Oracle vor atribui automat un nume arbitrar, generat de sistem, pentru a aplica acea regulă. Asta creează o bombă cu ceas pentru migration-urile viitoare. Când, în cele din urmă, trebuie să dai alter sau drop la acel tabel sau coloană, Alembic folosește operațiunea de drop constraint. Acea operațiune necesită strict numele exact al constrângerii țintă. Dacă lași baza de date să genereze numele, acesta va fi aproape sigur diferit în development față de cum este în staging sau producție. Ajungi să hardcodezi un nume de constrângere locală în scriptul tău de migration, care pică imediat atunci când este rulat pe un environment diferit, unde acel string random nu există. Pentru a repara asta, absolut fiecare constrângere din baza ta de date trebuie să aibă un nume explicit, determinist. Să faci asta manual pe sute de modele este plictisitor și ușor de uitat. Abordarea mai bună este să configurezi un dicționar de naming convention pe obiectul tău SQLAlchemy MetaData. Acest dicționar servește ca un template global pentru aplicația ta. Definești reguli pentru fiecare tip de constrângere. De exemplu, poți specifica ca fiecare index să fie denumit folosind prefixul i x, urmat de numele tabelului, urmat de numele coloanei. Setezi template-uri similare pentru unique constraints, check constraints și foreign keys. Apoi atașezi acest obiect MetaData configurat la clasa ta declarative base. Iată partea care contează. Odată ce acest dicționar este la locul lui, Alembic îți integrează automat naming convention-urile atât în funcția sa de autogenerate, cât și în operațiunile manuale. Când rulezi o comandă pentru a da autogenerate la un nou migration, Alembic se uită la modelele tale, vede o nouă constrângere și verifică dicționarul MetaData. Aplică template-ul tău, calculează numele explicit și scrie exact acel string în scriptul Python generat. Deoarece scriptul generat comandă explicit bazei de date să folosească acel nume specific, constrângerea va fi identică în absolut fiecare environment. Această integrare se extinde și la operațiunile Alembic rulate chiar în timpul procesului de upgrade. Dacă un script de migration include o operațiune de create table sau add column cu constrângeri inline cărora le lipsesc nume explicite, Alembic nu le pasează pur și simplu orbește către baza de date. Le interceptează, consultă template-ul de naming convention și atribuie numele determinist corect înainte de a executa comenzile pe baza de date. Un naming convention determinist garantează că o regulă creată pe mașina ta locală va avea exact același identificator atunci când ajunge pe serverele tale de producție, eliminând complet riscul constrângerilor cărora nu le poți da drop. Mersi de ascultare. Aveți grijă de voi, tuturor.
5

Migrări offline și generare SQL

4m 31s

Explorează cum să generezi scripturi SQL pure pentru administratorii tăi de baze de date în loc să rulezi Python direct pe baza de date de producție. Discutăm despre fluxul de execuție offline.

Descarcă
Salut, sunt Alex de la DEV STORIES DOT EU. Migrări de baze de date cu Alembic, episodul 5 din 8. În mediile enterprise extrem de reglementate, dezvoltatorii nu primesc aproape niciodată acces direct pentru a rula Python pe bazele de date din producție. Când sosește ziua de deploy, administratorii bazelor de date îți vor bloca de obicei accesul și vor solicita în schimb un script raw, care poate fi revizuit. Reducerea acestei diferențe între codebase-ul tău Python și procesul lor strict de deploy este gestionată de Offline Migrations și SQL Generation. În mod normal, Alembic se conectează la o bază de date live și execută modificări de schema direct prin acea conexiune. Dar când trebuie să predai un fișier plain text unei echipe DBA, folosești modul offline. Prin adăugarea flag-ului dash dash sql la comenzile tale de upgrade sau downgrade din terminal, Alembic își schimbă complet comportamentul de execuție. În loc să ruleze statement-urile pe un database engine, le randează ca un string continuu de SQL standard și le trimite direct la standard output. Poți redirecționa cu ușurință acest output din terminal într-un fișier text. Acest comportament dual nu este magic, este definit explicit în fișierul de environment al proiectului tău, denumit de obicei env dot py. Dacă te uiți în interiorul acelui fișier, vei găsi două funcții de rutare distincte. Prima este run migrations online. Această funcție creează un database engine live, face bind la o conexiune activă în contextul Alembic și rulează scripturile tale de migrare pas cu pas. A doua funcție este run migrations offline, iar aici are loc traducerea. Când pasezi flag-ul sql, Alembic detectează flag-ul și declanșează în schimb această funcție offline. Configurează contextul folosind doar un database URL. Nu se stabilește nicio conexiune la rețea și nu se instanțiază niciun engine. Apoi preia structurile tale de migrare Python și generează statement-urile exacte CREATE, ALTER sau DROP, le încadrează în blocuri de tranzacție standard BEGIN și COMMIT și formatează totul pentru dialectul specific al bazei tale de date. Aici e partea esențială. Deoarece modul offline nu se conectează niciodată la baza de date, scripturile tale de migrare nu se pot baza pe starea activă a bazei de date. Nu poți executa un statement SELECT în interiorul unei migrări offline pentru a verifica dacă există un rând și nu poți inspecta starea curentă a unui tabel înainte de a face o modificare. Dacă codul tău Python se așteaptă ca un database cursor să returneze date pentru a decide ce modificare de schema să facă, generarea offline va eșua. Scriptul trebuie să fie pur declarativ. Pur și simplu îi spune lui Alembic ce structuri să genereze. Imaginează-ți un dezvoltator care finalizează un feature branch local. A rulat migrările local în modul online pentru a verifica dacă totul funcționează pe baza de date de testare. Pentru release-ul de producție, rulează comanda de upgrade cu un start revision și un end revision specifice, adaugă flag-ul sql și direcționează output-ul către un fișier text. Rezultatul este un script SQL curat, secvențial. Dezvoltatorul predă acest fișier echipei DBA. Cei din echipa DBA îl pot citi, îl pot verifica în funcție de politicile lor stricte de securitate și îl pot aplica în timpul ferestrei de mentenanță folosind instrumente standard de administrare a bazelor de date. De asemenea, ai control asupra modului în care este generat acest output offline. În cadrul funcției run migrations offline, apelul context configure acceptă parametri care modifică SQL-ul randat. O cerință comună este convertirea variabilelor în valori literale. Prin activarea literal binds în configurație, te asiguri că orice date inserate în timpul migrării includ valorile reale direct în string-ul SQL, în loc să genereze parameter markers generici. Acest lucru asigură că output-ul este un script complet autonom, gata de execuție. Adevărata valoare a generării offline este predictibilitatea; aceasta transformă schimbările dinamice de stare Python în SQL static, auditabil, pe care orice deployment pipeline sau echipă de securitate îl poate verifica înainte de modificarea unui singur tabel. Asta e tot pentru acest episod. Mulțumesc pentru audiție și continuă să construiești!
6

Migrări batch pentru SQLite

4m 00s

Abordează provocarea modificării tabelelor în SQLite, care nu are suport complet pentru ALTER TABLE. Învață fluxul de lucru move and copy folosind operațiunile batch din Alembic.

Descarcă
Salut, sunt Alex de la DEV STORIES DOT EU. Alembic Database Migrations, episodul 6 din 8. Construiești o aplicație locală, îți testezi migrarea și încerci să dai drop la o singură coloană. Baza de date aruncă o eroare și descoperi un fapt surprinzător: o simplă comandă de drop column pur și simplu nu există în database engine-ul tău. Asta e realitatea când lucrezi cu SQLite și este exact motivul pentru care Alembic oferă Batch Migrations. SQLite are o arhitectură lightweight, cu suport foarte limitat pentru alterarea tabelelor existente. Poți adăuga o coloană la un tabel, dar dacă vrei să dai drop la o coloană, să schimbi tipul unei coloane sau să îi dai rename, database engine-ul pur și simplu nu suportă asta. Mulți developeri se lovesc de asta când încearcă să ruleze o operațiune standard de drop column în scriptul lor de Alembic. Funcționează perfect pe PostgreSQL, dar pe SQLite, dă crash. Alembic rezolvă această limitare folosind un pattern numit move and copy workflow. Din moment ce baza de date nu poate modifica structura tabelului in place, Alembic reconstruiește întregul tabel de la zero, în background. Ca să folosești acest feature, nu apelezi direct metodele standard de operare. În schimb, folosești un context manager numit batch alter table. Pasezi numele tabelului tău acestui context manager, iar apoi îți definești toate modificările structurale în interiorul acelui block. Când block-ul termină de executat, Alembic preia controlul și orchestrează înlocuirea tabelului. Hai să ne uităm la un scenariu specific. Ai un tabel numit user_data și trebuie să dai drop unei coloane numite bar. În interiorul scriptului tău, deschizi context manager-ul batch alter table pentru tabelul user_data. În interiorul block-ului, îi dai instrucțiunea să dea drop coloanei numite bar. Asta e tot codul Python pe care îl scrii. În momentul în care context manager-ul face exit, Alembic generează o secvență de comenzi SQL precise pentru a executa move and copy workflow. Mai întâi, Alembic citește structura curentă a tabelului tău. Generează un statement de create table pentru un tabel temporar complet nou. Acest nou tabel are exact aceeași schemă ca originalul, cu excepția faptului că lipsește coloana bar. Apoi, Alembic îți copiază datele. Rulează un statement de insert care dă select la toate rândurile existente din tabelul original și le face push în noul tabel temporar. Pentru că acea coloană bar nu mai există în noua schemă, acele date specifice sunt pur și simplu lăsate în urmă. Odată ce datele sunt copiate în siguranță, Alembic dă drop complet tabelului user_data original. În cele din urmă, dă rename tabelului temporar înapoi în user_data. Baza de date ajunge exact în starea pe care o voiai, iar aplicația ta nu știe niciodată că tabelul a fost complet reconstruit. Iată care e ideea cheie. Context manager-ul batch alter table îți grupează operațiunile pentru performanță. Dacă trebuie să dai drop la două coloane, să adaugi una nouă și să schimbi un data type, pui toate acele instrucțiuni în același context block. Alembic va compila toate acele modificări și va executa move and copy workflow exact o singură dată. Reconstruirea unui tabel mare este o operațiune costisitoare care implică read-uri și write-uri grele pe disc, așa că este crucial să o faci într-un singur pass. Operațiunile de tip batch transformă o limitare severă a engine-ului într-un detaliu de implementare complet invizibil, permițându-ți să scrii scripturi de migrare curate, database-agnostic, în timp ce Alembic se ocupă în siguranță de greul recreării tabelului, în background. Asta e tot pentru acest episod. Mulțumesc că ai ascultat și continuă să construiești!
7

Lucrul cu branch-uri

3m 42s

Stăpânește colaborarea în echipă gestionând fluxurile de migrare ramificate. Învață cum să identifici și să îmbini istoricele de revizuire divergente atunci când mai mulți dezvoltatori modifică baza de date.

Descarcă
Salut, sunt Alex de la DEV STORIES DOT EU. Migrări de baze de date cu Alembic, episodul 7 din 8. Un code merge dezordonat este enervant, dar de obicei doar pică un test local. Două scheme de baze de date în conflict, pe de altă parte, îți pot bloca întregul deployment pipeline. Faci merge la cod în main, dar brusc tool-ul tău de migrare a bazei de date se plânge de multiple heads. Asta e realitatea când lucrezi cu branches în Alembic, iar rezolvarea problemei necesită să înțelegi cum se face fork la timeline-ul bazei tale de date. Aceste branches apar natural în orice echipă. Developerul A lucrează la un feature și generează un script de migrare pentru a adăuga o tabelă de shopping cart. Acest nou script indică starea curentă a bazei de date, să o numim revizia 100, ca bază a sa. Între timp, Developerul B lucrează pe un alt branch și generează un script pentru a adăuga o coloană de cont. Scriptul său indică, de asemenea, revizia 100 ca bază. Ambii developeri testează local, totul funcționează perfect, iar ambele pull requests primesc merge în repository-ul principal. Acum ai două scripturi de migrare separate în proiectul tău, ambele pretinzând a fi succesorul imediat al reviziei 100. Timeline-ul migrării s-a împărțit în două căi paralele. Dacă rulezi comanda de upgrade a bazei de date la revizia head, Alembic se va opri imediat. Va arunca o eroare care spune că există multiple heads. Tool-ul refuză să ghicească ce migrare ar trebui aplicată prima, deoarece aplicarea modificărilor pe baza de date într-o ordine imprevizibilă este periculoasă. Pentru a rezolva asta, trebuie să reconciliezi fluxurile divergente folosind comanda merge din Alembic. Iată ideea cheie. Un merge în Alembic nu este ca un Git merge. Nu se uită în fișierele Python ca să încerce să-ți combine automat modificările de schemă într-un singur fișier. În schimb, comanda merge creează un script de migrare complet nou și gol. Acest nou script nu conține operațiuni pe baza de date. Nu modifică tabele și nu adaugă coloane. Întregul său scop este structural. În interiorul fișierului Python generat, variabila down revision este setată la un tuple care conține ID-urile de revizie ale ambelor scripturi divergente, în loc de un singur string. Această singură acțiune leagă cele două branches paralele la loc. Creează un nou head unificat pentru timeline. Când declanșezi comanda, de obicei îi pasezi cuvântul heads, ceea ce îi spune lui Alembic să găsească toate acele endpoints curente din istoricul migrării și să le dea merge. Poți, de asemenea, să atașezi un string ca mesaj pentru a documenta sincronizarea, la fel ca un commit message. Odată ce acest merge script este generat și primește commit în repository-ul tău, timeline-ul tău este din nou liniar. Data viitoare când rulezi comanda de upgrade, Alembic va executa ambele scripturi părinte într-o secvență sigură și apoi va pune un stamp pe baza de date cu noul ID al reviziei de merge. Integritatea structurală a istoricului bazei tale de date depinde de această sincronizare. Un branch în Alembic este doar un fork în istoricul migrării, iar rezolvarea lui înseamnă generarea unui script dedicat care acționează ca un nod fizic ce leagă acele căi divergente înapoi într-o singură secvență clară. Dacă găsești aceste episoade utile și vrei să susții emisiunea, poți căuta DevStoriesEU pe Patreon. Asta e tot pentru acest episod. Mulțumesc că m-ai ascultat și continuă să construiești!
8

Tehnici avansate pentru producție

3m 57s

Treci la nivelul următor cu cunoștințele tale despre Alembic folosind tehnici avansate. Acoperim invocarea programatică a comenzilor și partajarea unei conexiuni cu framework-uri de aplicații precum FastAPI.

Descarcă
Salut, sunt Alex de la DEV STORIES DOT EU. Alembic Database Migrations, episodul 8 din 8. Pentru aplicațiile moderne containerizate, să te bazezi pe scripturi manuale din command-line pentru a pregăti baza de date înainte ca aplicația să pornească este o bătaie de cap operațională. Aplicația ta ar trebui să fie suficient de inteligentă încât să își verifice și să își actualizeze propria schemă la startup. Pentru a face asta în siguranță, ai nevoie de Production Power-Ups. Majoritatea developerilor știu de Alembic doar ca de un tool de terminal. Tastezi o comandă de upgrade, iar el modifică baza de date. Dar interfața de command-line este doar un thin wrapper. Dedesubt se află API-ul programatic din Alembic. Poți declanșa migrări direct din codul aplicației tale Python. Asta permite framework-urilor de backend moderne să execute automat update-uri de schemă în timpul rutinei lor de startup, asigurându-se că baza de date și codul sunt mereu perfect sincronizate. Totuși, dacă faci asta într-un mod naiv, apare o problemă subtilă. Când rulezi o migrare programatic, Alembic folosește implicit comportamentul său standard. Citește fișierul de configurare, creează un database engine complet nou, deschide o conexiune, rulează migrarea și o închide. Dar aplicația ta tocmai a pornit. A creat deja un engine și a inițializat un connection pool. Să îl lași pe Alembic să deschidă o conexiune complet separată în timpul startup-ului este ineficient. Mai important, poate fi periculos. Dacă secvența de startup a aplicației tale ține un lock pe un tabel, conexiunea separată a lui Alembic va rămâne agățată așteptând acel lock, provocând un deadlock care îți va da crash la container. Asta este o problemă majoră și dacă rulezi teste automate pe o bază de date in-memory. În acel scenariu, o conexiune complet nouă duce către o bază de date complet goală, ceea ce înseamnă că migrările tale nu se vor aplica pe datele pe care le testezi de fapt. Rezolvi asta pasând conexiunea activă la baza de date a aplicației tale direct către Alembic. Asta se face folosind obiectul de configurare Alembic. Mai întâi, codul aplicației tale instanțiază un obiect de configurare, pe care îl îndreaptă către fișierul tău principal de inițializare. Aici este ideea de bază. Obiectul de configurare are un dicționar de atribute. Acesta acționează ca o punte pentru a pasa obiecte Python live în mediul de migrare. Obții o conexiune activă de la engine-ul aplicației tale și o atribui unei chei numite connection în interiorul acelui dicționar de atribute. Apoi, apelezi API-ul programatic din Alembic, mai exact comanda de upgrade, pasându-i obiectul tău de configurare modificat și spunându-i să facă upgrade la head revision. Dar Alembic nu știe automat ce să facă cu acea conexiune injectată. Trebuie să modifici fișierul de environment al migrării pentru a închide circuitul. În secțiunea fișierului tău de environment care gestionează migrările online, adaugi o verificare simplă înainte să aibă loc setup-ul. Instruiești scriptul să caute în atributele de configurare. Dacă găsește un obiect de tip connection acolo, dă skip la crearea unui nou engine. În schimb, configurează contextul de migrare pentru a folosi conexiunea pe care ai furnizat-o. Dacă nu găsește o conexiune în atribute, face un fallback sigur la comportamentul normal, creând un nou engine din URL-ul bazei de date. Acest fallback se asigură că tool-urile tale de command-line funcționează exact ca înainte, atunci când le rulezi local. Proiectându-ți sistemul în acest fel, transformi migrările dintr-o corvoadă externă de deployment într-o parte nativă și predictibilă a ciclului de viață al aplicației. Când o nouă instanță pornește, cere o conexiune, își gestionează propriile upgrade-uri în cadrul acelei sesiuni și trece fără probleme la servirea traficului. Asta încheie seria noastră despre migrări de baze de date. Te încurajez cu căldură să explorezi documentația oficială Alembic și să încerci aceste configurări programatice hands-on. Dacă ai idei pentru subiecte complet noi pe care ai vrea să le auzi, vizitează devstories dot eu și dă-ne de știre. Asta e tot pentru acest episod. Mersi că ai ascultat și continuă să construiești!