Retour au catalogue
Season 38 8 Épisodes 28 min 2026

Alembic Database Migrations

v1.18 — Édition 2026. Maîtrisez les migrations de bases de données avec Alembic 1.18 en Python. Apprenez à gérer les modifications de schéma, à utiliser autogenerate, à gérer les contraintes, à écrire des scripts hors ligne et à orchestrer efficacement les migrations de bases de données avec SQLAlchemy.

Bases de données Migrations de bases de données ORM
Alembic Database Migrations
Lecture en cours
Click play to start
0:00
0:00
1
L'importance des migrations
Découvrez pourquoi la gestion manuelle des schémas échoue à grande échelle et comment Alembic apporte le contrôle de version à votre base de données relationnelle. Nous explorons le modèle mental fondamental des migrations de bases de données et décortiquons l'anatomie de l'environnement Alembic.
3m 20s
2
Anatomie d'une révision
Parcourez le cycle de vie de votre toute première migration Alembic. Nous décomposons les fonctions upgrade et downgrade et révélons comment le suivi des versions fonctionne réellement au sein de la base de données.
3m 35s
3
La magie et les limites d'autogenerate
Découvrez comment Alembic détecte automatiquement les changements en comparant vos modèles SQLAlchemy aux métadonnées de la base de données en direct. Apprenez ce qu'il détecte sans faille et ce qui lui échappe.
3m 42s
4
L'importance du nommage des contraintes
Découvrez pourquoi s'appuyer sur des noms générés par la base de données pour les contraintes est la recette pour des désastres de migration. Apprenez à configurer une convention de nommage unifiée pour votre système.
3m 35s
5
Migrations hors ligne et génération de SQL
Découvrez comment générer des scripts SQL purs pour vos administrateurs de bases de données au lieu d'exécuter Python directement sur votre base de données de production. Nous discutons du flux d'exécution hors ligne.
4m 03s
6
Migrations par lots pour SQLite
Relevez le défi de la modification des tables dans SQLite, qui manque d'un support complet de ALTER TABLE. Apprenez le flux de travail move and copy en utilisant les opérations par lots d'Alembic.
3m 42s
7
Travailler avec les branches
Maîtrisez la collaboration en équipe en gérant les flux de migration ramifiés. Apprenez à identifier et à fusionner des historiques de révision divergents lorsque plusieurs développeurs modifient la base de données.
3m 07s
8
Optimisations pour la production
Améliorez vos connaissances d'Alembic avec des techniques avancées. Nous abordons l'invocation programmatique de commandes et le partage d'une connexion avec des frameworks d'application comme FastAPI.
3m 52s

Épisodes

1

L'importance des migrations

3m 20s

Découvrez pourquoi la gestion manuelle des schémas échoue à grande échelle et comment Alembic apporte le contrôle de version à votre base de données relationnelle. Nous explorons le modèle mental fondamental des migrations de bases de données et décortiquons l'anatomie de l'environnement Alembic.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Database Migrations avec Alembic, épisode 1 sur 8. Tu lances une commande de base de données manuelle directement sur ton serveur de production pour ajouter une seule colonne, et soudain, l'application plante. Ton code déployé s'attendait à une certaine structure, la base de données en a maintenant une autre, et il n'y a pas de simple bouton undo. C'est pour ça qu'on va voir pourquoi les migrations sont nécessaires. Quand un projet logiciel démarre, changer le schéma de la base de données, c'est facile. Tu drop les tables et tu les recrées. Mais une fois que tu as de vrais utilisateurs et de vraies données, ce n'est plus une option. Faire des modifications manuelles sur différents environnements comme le développement, le staging et la production finit par créer des incohérences. Le code de ton application dépend d'un état spécifique de la base de données. Quand cet état dérive, l'application plante. Alembic résout ça en agissant comme un version control pour le schéma de ta base de données. Tout comme tu suis l'historique de ton code source, Alembic suit l'historique de la structure de ta base de données. Pour utiliser Alembic, tu initialises un environnement de migration. C'est une structure de répertoires dédiée que tu commit dans ton repository de source control avec le code de ton application. Elle contient les instructions et la configuration nécessaires pour modifier ta base de données au fil du temps. L'environnement se compose de trois éléments principaux. Le premier, c'est le fichier de configuration à la racine, nommé alembic point ini. Ce fichier se trouve à la base de ton projet. Il stocke les paramètres de base, principalement l'URL de connexion à la base de données, pour dire à Alembic où se trouve réellement la base de données cible. Ensuite, il y a le répertoire versions. C'est là que sont stockés les scripts de migration. À chaque fois que tu as besoin de changer le schéma de la base de données, un nouveau script Python est créé dans ce dossier. Chaque script définit deux actions : une fonction upgrade pour appliquer le changement, et une fonction downgrade pour l'annuler. Si tu as besoin d'ajouter une table pour les profils utilisateurs, l'instruction exacte pour ce changement se trouve dans un script juste ici. Le dernier élément est un fichier appelé env point py. C'est facile de le confondre avec un fichier de configuration général de l'application ou un endroit pour stocker des variables système, mais ce n'est pas son but. Voici le point clé. Le fichier env point py fait spécifiquement le pont entre les modèles de ton application et le moteur de migration d'Alembic. Il configure le database engine, gère le cycle de vie de la connexion et, surtout, il charge tes metadata SQLAlchemy. Ça indique à Alembic à quoi ressemblent exactement tes modèles dans le code, pour qu'il sache à quel schéma de base de données ils doivent finalement correspondre. À chaque fois que tu invoques une commande Alembic, il exécute d'abord ce script env point py pour établir le contexte dont il a besoin pour fonctionner. Au lieu de te reposer sur une mémoire fragile de commandes de base de données manuelles, tu as un processus structuré et répétable. La vraie valeur de l'environnement Alembic, ce n'est pas juste qu'il exécute des commandes de manière sécurisée, mais qu'il crée un historique définitif et versionné de la façon exacte dont tes structures de données ont évolué depuis le premier jour. Si tu aimes le podcast et que tu veux soutenir l'émission, tu peux nous trouver en cherchant DevStoriesEU sur Patreon. Je voudrais prendre un moment pour te remercier de ton écoute, ça nous aide beaucoup. Passe une excellente journée !
2

Anatomie d'une révision

3m 35s

Parcourez le cycle de vie de votre toute première migration Alembic. Nous décomposons les fonctions upgrade et downgrade et révélons comment le suivi des versions fonctionne réellement au sein de la base de données.

Télécharger
Salut, ici Alex de DEV STORIES DOT EU. Migrations de base de données Alembic, épisode 2 sur 8. Tu t'es déjà demandé comment une base de données sait exactement quelle version du schéma elle exécute en ce moment ? Elle n'inspecte pas tes tables et ne devine pas en fonction des colonnes qui existent. Le secret se cache dans une seule table masquée, et comprendre comment elle se connecte à ton code, c'est le cœur de l'anatomie d'une révision. Pour modifier un schéma de base de données, tu dois d'abord créer un script de migration. Pour ça, tu lances la commande Alembic revision avec un court message descriptif, comme create account table. Alembic génère un nouveau fichier Python dans ton répertoire versions. Le nom du fichier commence par une string aléatoire, suivie de ton message. Cette string est un GUID partiel, un identifiant unique global. Alembic utilise ces identifiants au lieu d'entiers séquentiels pour éviter les merge conflicts quand plusieurs développeurs créent des migrations sur différentes branches en même temps. Si tu ouvres ce nouveau fichier Python, tu verras deux variables vers le haut : revision et down revision. La variable revision contient le GUID de ce script spécifique. La variable down revision contient le GUID du script qui vient juste avant. Voici le point essentiel. Les développeurs pensent souvent que les migrations sont appliquées dans l'ordre en fonction des timestamps de création des fichiers ou de l'ordre alphabétique des noms de fichiers. Ce n'est pas le cas. Alembic se base strictement sur la chain de down revision. Il lit ces variables à l'intérieur des fichiers pour construire une linked list de l'historique de ton schéma. Si un script ne pointe pas vers une révision précédente valide, la chain se brise. Sous ces variables de routage, tu trouveras deux fonctions vides : upgrade et downgrade. C'est ici que tu écris manuellement tes modifications de schéma. Dans notre scénario, on ajoute une table account. Dans la fonction upgrade, tu écris la logique pour créer la table, en définissant tes colonnes, comme une primary key de type entier et une string pour le nom du compte. La fonction downgrade doit faire exactement l'inverse. Si upgrade crée la table account, downgrade doit la drop. Chaque pas en avant doit avoir un pas en arrière correspondant et fiable. Une fois ton script écrit, tu l'appliques en lançant la commande Alembic upgrade, en pointant vers head, ce qui signifie la révision la plus récente de ta chain. Voici ce qui se passe en coulisses. Alembic se connecte à ta base de données et cherche une table appelée alembic version. Si c'est ta première migration, la table n'existe pas encore, donc Alembic la crée. Cette table a exactement une ligne et une colonne, qui stocke le GUID de la révision actuellement appliquée. Alembic vérifie cette table, regarde où en est la base de données actuellement, et exécute les fonctions upgrade de chaque script nécessaire pour atteindre la révision cible. Enfin, il met à jour la table version avec ton nouveau GUID. Si tu testes ta nouvelle feature account et que tu te rends compte que quelque chose ne va pas, tu peux faire un roll back proprement. Tu lances la commande Alembic downgrade, en passant un identifiant relatif comme moins un pour reculer d'une seule révision. Alembic regarde la version actuelle dans la base de données, trouve le script correspondant, et exécute sa fonction downgrade. Il drop la table account et met à jour la table version avec le GUID précédent. La chose la plus importante à retenir, c'est qu'un script de migration n'est pas juste une simple collection de commandes de base de données. C'est un node autonome dans une linked list qui donne à ta base de données un chemin précis pour avancer et reculer dans le temps. Merci d'avoir passé quelques minutes avec moi. À la prochaine, à plus.
3

La magie et les limites d'autogenerate

3m 42s

Découvrez comment Alembic détecte automatiquement les changements en comparant vos modèles SQLAlchemy aux métadonnées de la base de données en direct. Apprenez ce qu'il détecte sans faille et ce qui lui échappe.

Télécharger
Bonjour, ici Alex de DEV STORIES DOT EU. Migrations de base de données Alembic, épisode 3 sur 8. Faire aveuglément confiance à un outil automatisé pour écrire tes migrations de base de données, c'est prendre le risque de supprimer accidentellement tes tables en production. Le problème réside dans la compréhension de ce que l'outil voit réellement lorsqu'il compare ton code à la réalité, et c'est précisément ce que nous abordons aujourd'hui avec La magie et les limites d'autogenerate. Alembic possède une fonctionnalité essentielle appelée autogenerate. Lorsque tu exécutes une commande revision avec le flag autogenerate, Alembic effectue une comparaison. Tout d'abord, il se connecte à ta base de données en production et examine le schema actuel. Ensuite, il examine l'état cible défini par les models SQLAlchemy dans le code de ton application. Il compare ces deux états et identifie les différences. Il existe une idée fausse courante concernant cette étape. Autogenerate n'applique pas comme par magie ces modifications à ta base de données. Il écrit simplement un draft de script Python contenant les opérations de migration qu'il estime nécessaires pour que la base de données corresponde à tes models. Tu dois examiner ce script candidat avant de l'exécuter réellement sur ta base de données. Lorsqu'il compare ta base de données à tes models, autogenerate détecte avec fiabilité les modifications structurelles de base. Si tu ajoutes une nouvelle classe de model à ton code, Alembic prépare une instruction pour créer une table. Si tu supprimes une classe de model, il prépare une instruction pour drop cette table. Il détecte correctement quand tu ajoutes ou supprimes des colonnes, quand tu modifies une colonne pour autoriser les valeurs null, ou quand tu ajoutes des index basiques et des contraintes unique. Pour ces opérations standard, la fonctionnalité t'épargne une quantité massive de saisie manuelle. Voici le point crucial. Autogenerate présente des angles morts, car il ne peut pas lire dans tes pensées. Supposons que tu décides de renommer une table existante dans tes models SQLAlchemy. Tu mets à jour le code et exécutes la commande autogenerate, en t'attendant à ce qu'Alembic prépare une commande sûre pour alter le nom de la table. Au lieu de cela, il propose quelque chose de très dangereux. Il prépare une commande pour drop complètement l'ancienne table, détruisant ainsi toutes les données à l'intérieur, puis il prépare une seconde commande pour créer une toute nouvelle table avec le nouveau nom. Alembic fait cela car il constate uniquement que l'ancien nom de table existe dans la base de données mais est absent de tes models, et qu'un nouveau nom de table existe dans tes models mais est absent de la base de données. Il n'a aucun moyen de lier les deux comme un simple renommage. Tu dois modifier manuellement le script généré pour utiliser une opération rename table à la place. Exactement la même limitation s'applique au renommage des colonnes. Autogenerate interprétera une colonne renommée comme une instruction pour drop l'ancienne et en ajouter une nouvelle. Au-delà des renommages, il y a des modifications qu'autogenerate ignorera entièrement par défaut. Si tu modifies le data type d'une colonne, ou si tu modifies une valeur server default, Alembic ignorera ces différences. Tu peux configurer l'outil pour détecter les modifications de type et de default, mais tu dois activer explicitement ces paramètres dans la configuration de ton environnement. Même avec ces paramètres activés, il ne détectera jamais les modifications apportées aux objets sequence ou aux noms de contraintes. La façon la plus sûre de traiter autogenerate est de le voir comme un outil de dictée ultra-rapide qui gère le boilerplate pour toi, plutôt que comme un système intelligent qui comprend l'intention derrière tes modifications de code. Merci d'être resté avec moi. J'espère que tu as appris quelque chose de nouveau.
4

L'importance du nommage des contraintes

3m 35s

Découvrez pourquoi s'appuyer sur des noms générés par la base de données pour les contraintes est la recette pour des désastres de migration. Apprenez à configurer une convention de nommage unifiée pour votre système.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Migrations de bases de données Alembic, épisode 4 sur 8. Le moyen le plus simple de ruiner un deploy, c'est d'essayer de drop une contrainte de base de données à laquelle tu n'as jamais vraiment donné de nom. Ton script de migration marche parfaitement en local, mais l'environnement de staging vient de crasher, en se plaignant d'une foreign key manquante avec un nom imprévisible genre SYS C 0 0 2 9 3 3 4. Le coupable, c'est le fait de se reposer sur des identifiants générés par la base de données. Cet épisode couvre l'importance de nommer tes contraintes et comment automatiser ça. Beaucoup de devs supposent que l'object-relational mapper gère le drop des colonnes et de leurs règles associées de façon transparente. Ils définissent une unique constraint ou une foreign key dans leur modèle, omettent le nom pour gagner du temps, et passent à autre chose. Quand tu fais ça, c'est le moteur de base de données qui prend le relais. Des systèmes comme Postgres ou Oracle vont auto-assigner un nom arbitraire généré par le système pour appliquer cette règle. Ça crée une bombe à retardement pour tes futures migrations. Quand tu as finalement besoin d'alter ou de drop cette table ou cette colonne, Alembic utilise l'opération drop constraint. Cette opération exige strictement le nom exact de la contrainte cible. Si tu laisses la base de données générer le nom, il sera presque certainement différent en dev par rapport au staging ou à la prod. Tu finis par hardcoder un nom de contrainte local dans ton script de migration, qui fail immédiatement quand il est exécuté sur un environnement différent où cette string aléatoire n'existe pas. Pour corriger ça, chaque contrainte de ta base de données doit avoir un nom explicite et déterministe. Faire ça manuellement sur des centaines de modèles, c'est fastidieux et on l'oublie facilement. La meilleure approche, c'est de configurer un dictionnaire de naming convention sur ton objet MetaData SQLAlchemy. Ce dictionnaire sert de template global pour ton application. Tu définis des règles pour chaque type de contrainte. Par exemple, tu peux spécifier que chaque index doit être nommé en utilisant le préfixe i x, suivi du nom de la table, puis du nom de la colonne. Tu configures des templates similaires pour les unique constraints, les check constraints et les foreign keys. Ensuite, tu attaches cet objet MetaData configuré à ta declarative base class. Voici la partie importante. Une fois que ce dictionnaire est en place, Alembic intègre automatiquement tes naming conventions à la fois dans sa feature d'autogenerate et dans ses opérations manuelles. Quand tu lances une commande pour autogenerate une nouvelle migration, Alembic regarde tes modèles, voit une nouvelle contrainte, et check le dictionnaire MetaData. Il applique ton template, calcule le nom explicite, et écrit cette string exacte dans le script Python généré. Vu que le script généré ordonne explicitement à la base de données d'utiliser ce nom spécifique, la contrainte sera identique sur absolument tous les environnements. Cette intégration s'étend aux opérations Alembic lancées pendant le process d'upgrade lui-même. Si un script de migration inclut une opération create table ou add column avec des contraintes inline qui n'ont pas de nom explicite, Alembic ne les passe pas juste aveuglément à la base de données. Il les intercepte, consulte le template de naming convention, et assigne le bon nom déterministe avant d'exécuter les commandes de base de données. Une naming convention déterministe garantit qu'une règle créée sur ta machine locale partagera exactement le même identifiant quand elle atteindra tes serveurs de prod, éliminant complètement le risque de contraintes impossibles à drop. Merci d'avoir écouté. Prenez soin de vous, tout le monde.
5

Migrations hors ligne et génération de SQL

4m 03s

Découvrez comment générer des scripts SQL purs pour vos administrateurs de bases de données au lieu d'exécuter Python directement sur votre base de données de production. Nous discutons du flux d'exécution hors ligne.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Migrations de bases de données Alembic, épisode 5 sur 8. Dans les environnements d'entreprise très réglementés, les développeurs n'ont presque jamais d'accès direct pour exécuter du Python sur les bases de données de production. Quand le jour du deploy arrive, les administrateurs de bases de données te bloquent généralement l'accès et exigent à la place un script brut que l'on peut revoir. Faire le pont entre ta codebase Python et leur processus de deploy strict est géré par les Offline Migrations et la génération de SQL. Normalement, Alembic se connecte à une base de données live et exécute les changements de schéma directement via cette connexion. Mais quand tu dois fournir un fichier texte brut à une équipe de DBA, tu utilises le mode offline. En ajoutant le flag tiret tiret sql à tes commandes upgrade ou downgrade dans le terminal, Alembic change complètement son comportement d'exécution. Au lieu d'exécuter les statements sur un engine de base de données, il les rend sous forme d'une string continue de SQL standard et les dump directement sur la sortie standard. Tu peux facilement rediriger cette sortie du terminal vers un fichier texte. Ce double comportement n'est pas magique, il est explicitement défini dans le fichier d'environnement de ton projet, généralement nommé env point py. Si tu regardes à l'intérieur de ce fichier, tu trouveras deux fonctions de routage distinctes. La première est run migrations online. Cette fonction crée un engine de base de données live, bind une connexion active au context Alembic, et exécute tes scripts de migration étape par étape. La deuxième fonction est run migrations offline, et c'est là que la traduction se fait. Quand tu passes le flag sql, Alembic détecte le flag et déclenche cette fonction offline à la place. Elle configure le context en utilisant uniquement une URL de base de données. Aucune connexion réseau n'est établie, et aucun engine n'est instancié. Elle prend ensuite tes structures de migration Python et génère les statements CREATE, ALTER ou DROP exacts, les wrap dans des blocs de transaction BEGIN et COMMIT standards, et formate le tout pour ton dialecte de base de données spécifique. Voici le point essentiel. Parce que le mode offline ne se connecte jamais vraiment à la base de données, tes scripts de migration ne peuvent pas se baser sur l'état actif de la base de données. Tu ne peux pas exécuter un statement SELECT à l'intérieur d'une migration offline pour vérifier si une ligne existe, et tu ne peux pas inspecter l'état actuel d'une table avant de faire un changement. Si ton code Python s'attend à ce qu'un curseur de base de données retourne des données pour décider quel changement de schéma faire, la génération offline va échouer. Le script doit être purement déclaratif. Il dit simplement à Alembic quelles structures générer. Prends l'exemple d'un développeur qui termine une feature branch en local. Il a lancé les migrations en local en mode online pour vérifier que tout fonctionne sur sa base de données de test. Pour la release en production, il lance la commande upgrade avec une start revision et une end revision spécifiques, ajoute le flag sql, et redirige la sortie vers un fichier texte. Le résultat est un script SQL propre et séquentiel. Le développeur transmet ce fichier à l'équipe de DBA. Les DBA peuvent le lire, le vérifier par rapport à leurs politiques de sécurité strictes, et l'appliquer pendant la fenêtre de maintenance en utilisant des outils d'administration de base de données standards. Tu as aussi le contrôle sur la façon dont cette sortie offline est générée. À l'intérieur de la fonction run migrations offline, l'appel context configure accepte des paramètres qui ajustent le SQL rendu. Un besoin courant est de convertir les variables en valeurs littérales. En activant les literal binds dans la configuration, tu t'assures que toute donnée insérée pendant la migration inclut les valeurs réelles directement dans la string SQL, plutôt que de sortir des marqueurs de paramètres génériques. Ça garantit que la sortie est un script complètement autonome, prêt pour l'exécution. La vraie valeur de la génération offline, c'est la prévisibilité. Ça transforme les changements d'état dynamiques de Python en SQL statique et auditable que n'importe quelle pipeline de deploy ou équipe de sécurité peut vérifier avant qu'une seule table ne soit modifiée. C'est tout pour cet épisode. Merci de ton écoute, et continue à développer !
6

Migrations par lots pour SQLite

3m 42s

Relevez le défi de la modification des tables dans SQLite, qui manque d'un support complet de ALTER TABLE. Apprenez le flux de travail move and copy en utilisant les opérations par lots d'Alembic.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Alembic Database Migrations, épisode 6 sur 8. Tu développes une app en local, tu testes ta migration, et tu essaies de drop une seule colonne. La base de données te renvoie une erreur, et tu découvres un fait surprenant : la commande drop column n'existe fondamentalement pas dans ton moteur de base de données. C'est la réalité quand tu bosses avec SQLite, et c'est exactement pour ça qu'Alembic propose les Batch Migrations. SQLite a une architecture légère avec un support très limité pour altérer les tables existantes. Tu peux ajouter une colonne à une table, mais si tu veux drop une colonne, changer un type de colonne ou renommer une colonne, le moteur de base de données ne le supporte tout simplement pas. Beaucoup de devs rencontrent ce problème quand ils essaient de lancer une opération drop column standard dans leur script Alembic. Ça marche parfaitement sur PostgreSQL, mais sur SQLite, ça crash. Alembic résout cette limitation en utilisant un pattern appelé le workflow move and copy. Vu que la base de données ne peut pas modifier la structure de la table in place, Alembic reconstruit la table entière from scratch en arrière-plan. Pour utiliser cette feature, tu n'appelles pas directement les méthodes d'opération standards. À la place, tu utilises un context manager appelé batch alter table. Tu passes le nom de ta table à ce context manager, et ensuite tu définis tous tes changements structurels à l'intérieur de ce block. Quand le block a fini de s'exécuter, Alembic prend le relais et orchestre le remplacement de la table. Regardons un scénario spécifique. Tu as une table nommée user_data, et tu dois drop une colonne appelée bar. Dans ton script, tu ouvres le context manager batch alter table pour la table user_data. À l'intérieur du block, tu lui dis de drop la colonne nommée bar. C'est tout le code Python que tu as à écrire. Au moment où le context manager se termine, Alembic génère une séquence de commandes SQL précises pour exécuter le workflow move and copy. D'abord, Alembic lit la structure actuelle de ta table. Il génère un statement create table pour une toute nouvelle table temporaire. Cette nouvelle table a exactement le même schema que l'originale, sauf qu'il manque la colonne bar. Ensuite, Alembic copie tes données. Il lance un statement insert qui select toutes les rows existantes de la table d'origine et les pousse dans la nouvelle table temporaire. Comme la colonne bar n'existe plus dans le nouveau schema, ces données spécifiques sont tout simplement laissées de côté. Une fois que les données sont copiées de manière safe, Alembic drop entièrement la table user_data d'origine. Enfin, il renomme la table temporaire pour lui redonner le nom user_data. La base de données se retrouve exactement dans l'état que tu voulais, et ton app ne sait jamais que la table a été complètement reconstruite. Voici le point clé. Le context manager batch alter table batch tes opérations ensemble pour les performances. Si tu as besoin de drop deux colonnes, d'en ajouter une nouvelle, et de changer un data type, tu mets toutes ces instructions dans le même context block. Alembic va compiler tous ces changements et exécuter le workflow move and copy une seule fois. Reconstruire une grosse table est une opération coûteuse qui implique de lourdes lectures et écritures sur le disque, donc le faire en une seule passe est crucial. Les batch operations transforment une grosse limitation du moteur en un détail d'implémentation complètement invisible, te permettant d'écrire des scripts de migration propres et database-agnostic, pendant qu'Alembic gère le gros du travail de recréation de table de manière safe en arrière-plan. C'est tout pour cet épisode. Merci d'avoir écouté, et continue de développer !
7

Travailler avec les branches

3m 07s

Maîtrisez la collaboration en équipe en gérant les flux de migration ramifiés. Apprenez à identifier et à fusionner des historiques de révision divergents lorsque plusieurs développeurs modifient la base de données.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Migrations de base de données Alembic, épisode 7 sur 8. Un merge de code un peu sale, c'est agaçant, mais en général ça fait juste planter un test en local. Par contre, deux schémas de base de données en conflit peuvent bloquer tout ton pipeline de déploiement. Tu merges ton code sur main, mais soudain, ton outil de migration de base de données se plaint d'avoir plusieurs heads. C'est la réalité quand tu bosses avec des branches dans Alembic, et pour résoudre ça, tu dois comprendre comment la timeline de ta base de données se fork. Les branches apparaissent naturellement dans n'importe quel environnement d'équipe. Le développeur A bosse sur une feature et génère un script de migration pour ajouter une table de panier d'achat. Ce nouveau script pointe vers l'état actuel de la base de données, disons la révision 100, comme base. Pendant ce temps, le développeur B travaille sur une autre branche et génère un script pour ajouter une colonne account. Son script pointe lui aussi vers la révision 100 comme base. Les deux développeurs testent en local, tout marche bien, et les deux pull requests sont mergées sur le repo principal. Tu as maintenant deux scripts de migration distincts dans ton projet, qui prétendent tous les deux être le successeur immédiat de la révision 100. La timeline des migrations s'est séparée en deux chemins parallèles. Si tu lances la commande pour faire un upgrade de la base de données vers la révision head, Alembic va s'arrêter immédiatement. Il va renvoyer une erreur indiquant qu'il y a plusieurs heads. L'outil refuse de deviner quelle migration appliquer en premier, parce qu'appliquer des changements de base de données dans un ordre imprévisible, c'est dangereux. Pour résoudre ça, tu dois réconcilier les flux divergents en utilisant la commande merge d'Alembic. Voici le truc à comprendre. Faire un merge dans Alembic, ce n'est pas comme un merge Git. Ça ne va pas regarder à l'intérieur des fichiers Python pour essayer de combiner automatiquement tes changements de schéma dans un seul fichier. À la place, la commande merge crée un script de migration complètement nouveau et vide. Ce nouveau script ne contient aucune opération sur la base de données. Il ne modifie pas les tables et n'ajoute pas de colonnes. Son seul but est structurel. À l'intérieur du fichier Python généré, la variable down revision est définie sur un tuple contenant les ID de révision des deux scripts divergents, plutôt que sur une simple string. Cette simple action relie les deux branches parallèles entre elles. Ça crée un nouveau head unifié pour la timeline. Quand tu lances la commande, tu lui passes généralement le mot heads, ce qui dit à Alembic de trouver tous les endpoints actuels dans ton historique de migration et de les merger. Tu peux aussi attacher une string de message pour documenter la synchronisation, un peu comme un message de commit. Une fois que ce script de merge est généré et commité sur ton repo, ta timeline est à nouveau linéaire. La prochaine fois que tu lances la commande upgrade, Alembic exécutera les deux scripts parents dans une séquence sûre, puis marquera la base de données avec le nouvel ID de révision mergé. L'intégrité structurelle de l'historique de ta base de données dépend de cette synchronisation. Une branche Alembic, c'est juste un fork dans ton historique de migration, et la corriger implique de générer un script dédié qui agit comme un nœud physique reliant ces chemins divergents en une seule séquence claire. Si tu trouves ces épisodes utiles et que tu veux soutenir l'émission, tu peux chercher DevStoriesEU sur Patreon. C'est tout pour celui-ci. Merci d'avoir écouté, et continue de développer !
8

Optimisations pour la production

3m 52s

Améliorez vos connaissances d'Alembic avec des techniques avancées. Nous abordons l'invocation programmatique de commandes et le partage d'une connexion avec des frameworks d'application comme FastAPI.

Télécharger
Salut, c'est Alex de DEV STORIES DOT EU. Migrations de base de données Alembic, épisode 8 sur 8. Pour les applications conteneurisées modernes, s'appuyer sur des scripts en command-line manuels pour préparer ta base de données avant que ton app ne démarre est un vrai casse-tête opérationnel. Ton app devrait être assez intelligente pour vérifier et mettre à jour son propre schema au démarrage. Pour faire ça en toute sécurité, tu as besoin des Production Power-Ups. La plupart des devs ne connaissent Alembic que comme un outil de terminal. Tu tapes une commande upgrade, et ça modifie la base de données. Mais l'interface command-line n'est qu'un simple wrapper. En dessous, il y a l'API programmatique d'Alembic. Tu peux déclencher des migrations directement depuis le code de ton app Python. Ça permet aux frameworks backend modernes d'exécuter automatiquement les mises à jour de schema pendant leur routine de démarrage, pour garantir que le code et la base de données soient toujours parfaitement synchronisés. Cependant, faire ça naïvement introduit un problème subtil. Quand tu lances une migration de façon programmatique, Alembic utilise son comportement par défaut. Il lit ton fichier de configuration, crée un tout nouveau database engine, ouvre une connection, lance la migration, et la ferme. Mais ton app vient juste de démarrer. Elle a déjà créé un engine et initialisé un connection pool. Laisser Alembic créer une connection entièrement séparée pendant le démarrage, c'est inefficace. Plus important encore, ça peut être dangereux. Si la séquence de démarrage de ton app maintient un lock sur une table, la connection séparée d'Alembic va rester bloquée en attendant ce lock, ce qui va causer un deadlock qui fait crasher ton container. C'est aussi un problème majeur si tu lances des tests automatisés sur une base de données in-memory. Dans ce scénario, une toute nouvelle connection pointe vers une base de données complètement vide, ce qui veut dire que tes migrations ne s'appliqueront pas aux données que tu es en train de tester. Tu résous ça en passant la connection active de ton app directement à Alembic. Ça se fait en utilisant l'objet de configuration d'Alembic. D'abord, le code de ton app instancie un objet de configuration, en le faisant pointer vers ton fichier d'initialisation principal. Voici l'astuce clé. L'objet de configuration possède un dictionnaire d'attributs. Ça sert de pont pour passer des objets Python live dans l'environnement de migration. Tu récupères une connection active depuis l'engine de ton app, et tu l'assignes à une clé appelée connection dans ce dictionnaire d'attributs. Ensuite, tu appelles l'API programmatique d'Alembic, plus précisément la commande upgrade, en lui passant ton objet de configuration modifié et en lui disant de faire un upgrade vers la head revision. Mais Alembic ne sait pas automatiquement quoi faire de cette connection injectée. Tu dois modifier ton fichier d'environnement de migration pour boucler le circuit. Dans la section de ton fichier d'environnement qui gère les online migrations, tu ajoutes une simple vérification avant que le setup ne se fasse. Tu dis au script de regarder dans les attributs de configuration. S'il y trouve un objet connection, il skip la création d'un nouvel engine. À la place, il configure le contexte de migration pour utiliser la connection que tu as fournie. S'il ne trouve pas de connection dans les attributs, il fait un fallback sécurisé vers son comportement normal, en créant un nouvel engine à partir de l'URL de la base de données. Ce fallback garantit que tes outils en command-line fonctionnent toujours exactement comme avant quand tu les lances en local. En concevant ton système de cette façon, tu transformes les migrations d'une corvée de deploy externe en une partie native et prévisible du cycle de vie de l'app. Quand une nouvelle instance démarre, elle demande une connection, gère ses propres upgrades dans cette session, et passe de façon transparente au traitement du traffic. Ça conclut notre série sur les migrations de base de données. Je t'encourage vivement à explorer la documentation officielle d'Alembic et à tester ces configurations programmatiques par toi-même. Si tu as des idées pour de tout nouveaux sujets que tu aimerais entendre, visite devstories dot eu et fais-le-nous savoir. C'est tout pour cet épisode. Merci d'avoir écouté, et continue à développer !