Posty oznaczone etykietą sql

Migracje struktur baz danych w Django

Nie tak dawno temu wielu zarzucało Django, że w przeciwieństwie do Railsów nie posiada wbudowanego rozwiązania umożliwiającego wersjonowanie i modyfikowanie struktur bazodanowych. Niedługo po tym pojawił się South - dosyć obiecujące rozwiązanie, które oczywiście szybko przygarnąłem do projektów. Z czasem jednak okazało się, że architektura tego rozwiązania ma szereg wad.

Na południe

Podstawowym problemem a zarazem zaletą South jest związek migracji z aplikacjami Django. To poszczególne aplikacje są "dostawcami" migracji. Ma to na celu umożliwienie łatwiejszego utrzymania reusable apps, których upgrade w projektach był bez South bardzo trudny - wymagał poznania zmian struktury i własnoręcznego przygotowania skryptów SQL. O ile było to mozolne ale do zrobienia, to ustalenie migracji danych nie sposób było odtworzyć. Dzięki South sprawa się uprościła.

Podczas utrzymania systemu pojawia się jednak kilka problemów, na które South już częściowo jest odporny:

  • kolejność wykonywania migracji (changesetów) jest bardzo istotna
  • często istnieje potrzeba customizacji reusable apps "pod projekt"

South uruchamia migracje kolejno wg listy settings.INSTALLED_APPS, a dalej w porządku leksykograficznym nazw plików migracyjnych. Jednak nie zawsze jest to dobra kolejność. Choć problem ten został częściowo rozwiązany przez mechanizm zależności, to nie zawsze jest on idealnym rozwiązaniem:

System migracji wbudowany w Django

Niedawno developerzy Django zapowiedzieli, że od wersji 1.7 będzie wbudowane wsparcie dla migracji. Po zapoznaniu się z treścią dokumentu widzimy zmutowanego South. Teraz developerzy reusable apps przygotowują swoje aplikacje pod to "jedynie słuszne" i niestety wadliwe rozwiązanie. Ten mechanizm migracji nie sprawdzi się w większych projektach, bo ma w sobie te same wady, które posiada South. Django developers podjęli kolejną fatalną decyzję projektową. Trochę mnie to nie dziwi, bo kiedy tracą ogrom czasu i sił na pierdoły, to na inne tematy nie mają należytego czasu.

Za wadę obydwóch rozwiązań uważam ścisły związek z ORM, oraz tym samym przygotowywanie migracji w Pythonie. To pozwala niezbyt rozsądnym programistom chadzać na zwodnicze skróty, np. odwoływać się do funkcji/metod wyparowujących z czasem z projektu czy używać modeli bezpośrednio z models.py zamiast z zamrożonych definicji... Migracje schematów baz danych są związane tylko z bazami danych i warstwa aplikacji jest w tym procesie nie tylko zbędna, ale też furtką dla złych praktyk oraz nawet swego rodzaju narzutem.

Jedynymi zaletami migracji South/Django jest ich prostota i automatyczne generowanie.

Jak powinno zarządzać się zmianami struktury i danych w bazie

  • obowiązujące changesety powinny być prowadzone project-wide (Nashvegas, Liquibase - przy czym Nashvegas jest skopany - nie używać)
  • reusable apps powinny dostarczać jedynie bazowe changesety, które maintainer projektu mógłby świadomie wybierać do migracji project-wide
  • powinno istnieć narzędzie ułatwiające opracowywanie oraz importowanie changesetów do projektu

Dlaczego to zadziała?

  • mamy kontrolę nad każdym changesetem, w tym wprowadzania potrzebnych zmian
  • kolejność wykonywania changesetów jest niezmienna, niezależnie od zainstalowanych reusable apps i zawartości settings.INSTALLED_APPS
  • mamy możliwość dodawania w cały proces swoich changesetów (customizacji) z zachowaniem precyzji w kolejności ich wykonania
  • migracje baz danych są niezależne od ORM - struktura BD może się nieco różnić, a także mamy swobodę w budowaniu różnych mappingów w warstwie aplikacji
  • w migracjach SQL nie da się odwoływać do warstwy aplikacji, zatem są odporne na zmiany samej aplikacji i wykonają się zawsze (niezależnie od zmian w warstwie aplikacji)

W praktyce, w dużych projektach, używam Liquibase wraz z dodatkiem Liquimigrate do Django. To działa ZAWSZE. Kosztem jest brak automatu przy tworzeniu changesetów, ale SQL jest wygodniejszy i lepszy do tego zastosowania.

Liquimigrate docelowo widzę jako pakiet niezależny od Django, ale z mostkami do środowiska Django i innych frameworków, które pozwolą na łatwiejszą integrację i konfigurację.

System migracji Django 1.7 będzie niestety w takich projektach bezużyteczny, a sam framework rozwija się sukcesywnie w niezbyt dobrym kierunku.