Een krachtige oplossing voor databasemigraties

Database instantie

We hebben het ons allemaal wel eens afgevraagd: hoe kan ik zorgen dat een database op elke omgeving exact hetzelfde gecreëerd wordt? Hoe kan ik het beste omgaan met nieuwe wijzigingen en deze op een handige manier uitrollen? En niet te vergeten – hoe kan ik voorkomen dat nieuwe wijzigingen de boel kapot maken? Kan ik ook een rollback doen als dat nodig is?

Dit zijn belangrijke problemen die we als ontwikkelaars geheid een keer tegenkomen. Gelukkig hoef je hier niet over te piekeren – dat hebben anderen namelijk al gedaan voor ons. Het resultaat is een krachtige oplossing voor deze vraagstukken: Alembic.

Wat is Alembic

Alembic is een database migratie tool die is ontworpen voor gebruik met SQLAlchemy en Python. Met deze set aan tools kan je een relationele database ontwerpen met Python objecten, automatisch migraties genereren en migraties testen. Dit werkt met SQLAlchemy; een Object Relational Mapper (ORM) die data uit een object-oriented programmeertaal vertaald naar een relationele database. In de documentatie van SQLAlchemy lees je hoe je een database structuur onder kan brengen in objecten.

Dit biedt grote voordelen: je ontwerp is met één commando uit te rollen op een verse database, al je migraties worden met unit tests doorgetest op up- én down revisies, en je ontwerp wordt vergeleken met je migraties. Deze werkwijze helpt enorm om fouten te voorkomen in je werk.

De eerste migratie

Zodra je een Alembic omgeving hebt gemaakt (hier lees je hoe) kun je de eerste migratie genereren. Een migratie is een Python bestand wat alle database queries bevat die nodig zijn om de betreffende wijzigingen uit te voeren. Een migratie kan je automatisch genereren met het volgende command:

$ alembic revision --autogenerate -m “revision name”

Het gegenereerde bestand bevat alle (nieuwe) wijzigingen in je modellen. In dit bestand staan de commands om te upgraden en downgraden. Ook zie je het ID van de huidige en voorgaande revisie. Nieuwe wijzigingen in je modellen kun je borgen door hetzelfde command te draaien. Dan wordt er weer een nieuwe migratie gemaakt met de wijzigingen. Dit is in zekere zin versiebeheer voor je database.

Als je klaar bent met je migratie(s), kun je verbinden met de database en vervolgens de wijzigingen uitrollen:

alembic upgrade head

Of eventueel terugzetten, bijvoorbeeld één revisie terug:

alembic downgrade -1

Revisies testen

Deze opzet is heel fraai, maar hoe weet je nou dat het allemaal wel gaat (en blijft) werken? Dat kunnen we op voorhand testen met ingebouwde tests van Pytest Alembic. Deze plugin bevat de volgende tests:

  • test_single_head_revision: Test of er maar één head revision bestaat.
  • test_upgrade: Test of de revisies van eerste naar laatste uitgevoerd kunnen worden.
  • test_model_definitions_match_ddl: Test of de staat van de migraties overeenkomt met de staat van de modellen.
  • test_up_down_consistency: Test of de revisies van laastste naar eerste gedowngraded kunnen worden.

 

De tests kun je eenvoudig als volgt gebruiken, bijvoorbeeld in het bestand tests/test_migrations.py:


from pytest_alembic.tests import (
    test_model_definitions_match_ddl,
    test_single_head_revision,
    test_up_down_consistency,
    test_upgrade,

Dit zorgt ervoor dat deze tests automatisch worden uitgevoerd als je Pytest draait. Om dat voor elkaar te krijgen moet je nog wel wat voorwerk doen. Minimaal moet je deze fixture toevoegen om tegen de Alembic runner te vertellen waar de tests moeten draaien. Ik zou aanraden om dit in `tests/conftest.py` te zetten:


@pytest.fixture
def alembic_engine():
    """Override this fixture to provide pytest-alembic powered tests with a database handle.
    """
    return sqlalchemy.create_engine("<database>:///")

 

Meer informatie hierover is te vinden in de Pytest Alembic docs.

Deze tests zorgen er samen voor dat je veruit de meeste fouten in je wijzigingen op voorhand al detecteerd. Dat maakt deze werkwijze veel minder foutgevoelig dan wijzigingen handmatig of met scriptjes aanbrengen. En niet te vergeten, dit maakt het triviaal om een nieuwe instantie van de database uit te rollen. Al met al een zeer waardevolle tool!

Software Engineer

Meer weten?

"*" geeft vereiste velden aan

Privacyverklaring*

We hebben het ons allemaal wel eens afgevraagd: hoe kan ik zorgen dat een database op elke omgeving exact hetzelfde gecreëerd wordt? Hoe kan ik het beste omgaan met nieuwe wijzigingen en deze op een handige manier uitrollen? En niet te vergeten – hoe kan ik voorkomen dat nieuwe wijzigingen de boel kapot maken? Kan ik ook een rollback doen als dat nodig is?

Software Engineer

Meer weten?

"*" geeft vereiste velden aan

Privacyverklaring*

Dit artikel delen

Bekijk ook deze artikelen

Deze workshop is opgedeeld in een aantal onderdelen: Interactieve sessie over energie Hierin vragen we de kinderen wat ze al weten over energie in het algemeen. Hierbij helpt het als...
Doel van het project  In Nederland wordt steeds meer elektriciteit verbruikt en opgewekt dan het stroomnet aankan. Daarnaast doen we dat op grote schaal op hetzelfde moment, waardoor er grote...
Ongeveer vijf jaar geleden zijn we begonnen met een aantal maatwerk trainingen ter ondersteuning van ons werk bij klanten. Door uitbreidingen en professionaliseringsslagen is dit uitgegroeid tot de Energy Academy:...

Samen met ons bouwen aan een duurzame toekomst? Neem contact op!

Maak impact. Samen. Jij ook?

"*" geeft vereiste velden aan

Privacyverklaring*