System migracji baz danych dla projektów legacy bez ORM
W starszych systemach bez ORM migracje skryptów DDL/DML wymagają ścisłej kontroli. Proponowane podejście organizuje repozytorium i tabele stanu dla sekwencyjnego stosowania zmian w środowiskach testowych i produkcyjnych. Zapewnia to śledzenie, wsparcie danych i przewidywalność wdrożeń na relacyjnych bazach danych z ACID.
Podejście minimalizuje boilerplate w skryptach, automatyzuje weryfikację i logowanie. Skrypty dzielą się na typy: inicjalizacja, baseline, wersjonowane i powtarzalne. Każdy typ stosowany jest według reguł, eliminując duplikaty i zapewniając monotoniczność wersji.
Struktura repozytorium Git
Skrypty grupuje się według typów i stosuje w stałej kolejności:
- Inicjalizacja środowiska — jednokrotnie dla tworzenia użytkowników, ról, baz danych i schematów. Zależy od środowiska (test/prod), wykonywane za pomocą psql.
- Baseline — jednokrotnie na pustym schemacie dla początkowej wersji z prod i tabel kontrolnych.
- Wersjonowane — sekwencyjnie według rosnących wersji (integer), tylko raz, w transakcji z logiem czasu i użytkownika.
- Powtarzalne — przy zmianie SHA256 lub braku rekordu, po wersjonowanych, dla widoków/procedur/triggerów bez modyfikowalnych danych.
Typy obiektów:
- Inicjalizacja: użytkownicy, role, bazy danych, schematy.
- Baseline: tabele, dane, widoki, procedury, triggery.
- Wersjonowane: zmiany schematu, migracje danych.
- Powtarzalne: widoki, procedury, triggery.
Ta struktura inspirowana jest Flyway, ale dostosowana do ręcznych procesów bez zewnętrznych narzędzi.
Tabele stanu w schemacie
W każdym schemacie tworzone są tabele pomocnicze do śledzenia:
- dbmigration_versions (version_id, is_baseline, created_at, created_by, created_from) — historia skryptów baseline i wersjonowanych.
- dbmigration_repeatable (sha256sum, relative_path, created_at, created_by, created_from) — historia powtarzalnych, pozwala na ponowne zastosowanie przy zmianach.
Tabele zapewniają weryfikację przed zastosowaniem: skrypt jest wykonywany, jeśli rekordu brak lub checksum się zmienił. Logi obejmują użytkownika i timestamp dla audytu.
Wdrażanie w środowisku deweloperskim
W CI/CD (GitLab pipeline) klonuje się gałąź ze zmianami, następnie dla każdego schematu:
$ git clone <url zawierający zmiany w schematach baz danych>
$ USER_PASSWORD=topsecret123 dbmigration.py update --host <host> --port <port> --dbname <db> --user <user_name> schema1 ./db/schema1
$ USER_PASSWORD=topsecret123 dbmigration.py update --host <host> --port <port> --dbname <db> --user <user_name> schema2 ./db/schema2
To automatycznie stosuje oczekujące skrypty, zachowując dane.
Proces w produkcji
Obsługiwane jest hot deployment bez przestojów. Wcześniej testowane jest w UAT z testami smoke.
Kroki:
- Rozpakować archiwum:
tar xzvf system-x.y.z.tar.gz. - Dla schematu:
cd system-x.y.z/schema1. - Wygenerować skrypt migracyjny:
USER_PASSWORD=topsecret123 dbmigration.py verify --host <host> --port <port> --dbname <db> --user <user_name> --build-update-script ./schema1_migrate.sql schema1 ./db/schema1. - Przegląd schema1_migrate.sql pod kątem breaking changes.
- Zastosować:
PGPASSWORD=topsecret123 psql -h <host> -p <port> -U <user> -d <database> -v schema_name=<schema1> -f "schema1_migrate.sql".
Powtórzyć dla schematów. Tryb verify pozwala na podgląd bez zmian.
Kluczowe praktyki
- Fix forward: zamiast rollback, nowa migracja naprawia błędy, zachowując dane.
- Non-breaking changes: dodawać tabele/pola, usuwać po wydaniu, gdy nie są używane. Pozwala na równoległą pracę wersji na jednej bazie danych.
- Śledzenie na poziomie schematu: wersje per schema, nie per DB.
- Wstępna weryfikacja: generacja skryptów do przeglądu.
- Zachowanie danych: przyrostowe aktualizacje bez drop/recreate.
Co jest ważne
- Zautomatyzowane śledzenie eliminuje ręczny boilerplate i błędy w skryptach.
- Monotoniczne wersje z transakcjami zapewniają spójność stanów.
- Wsparcie hotfix dla różnych wersji (prod/UAT/dev) przez skrypty wersjonowane.
- Audyt przez tabele: kto/kiedy/co zastosował.
- Niezależność od RDBMS dla baz danych zgodnych z ACID.
— Editorial Team
Brak komentarzy.