Celem tego artykułu jest pokazanie narzędzi, które mogą znacznie uprościć proces rozwijania baz danych w ramach projektów PHP, wykorzystujących systemy zarządzania bazami danych PostgreSQL, na przykładzie biblioteki . Informacje zawarte w tym artykule będą przede wszystkim przydatne dla deweloperów, którzy chcą maksymalnie wykorzystać możliwości PostgreSQL, ale napotykają problemy z utrzymywaniem logiki biznesowej przeniesionej do bazy danych.
Artykuł nie będzie opisywał zalet ani wad przechowywania logiki biznesowej w bazie danych. Zakłada się, że wybór został już dokonany przez czytelnika.
Zostaną omówione następujące kwestie:
W jakiej formie przechowywać zrzut struktury bazy danych w systemie kontroli wersji (dalej w tekście — VCS)
- Jak śledzić zmiany w strukturze bazy danych po zapisaniu zrzutu
- Jak przenosić zmiany w strukturze bazy danych na inne środowiska bez konfliktów i gigantycznych plików migracji
- Jak zorganizować proces równoległej pracy nad projektem kilku deweloperów
- Jak bezpiecznie wprowadzać większą ilość zmian w strukturze bazy danych na środowisko produkcyjne
- SchemaKeeper
jest zaprojektowany do pracy z procedurami składowanymi napisanymi w języku PL/pgSQL W jakiej formie przechowywać zrzut struktury bazy danych w VCS
oferuje funkcję
Biblioteka saveDump , która zapisuje strukturę wszystkich obiektów z bazy danych w postaci osobnych plików tekstowych. Na wyjściu tworzony jest katalog zawierający strukturę bazy danych, podzieloną na pogrupowane pliki, które łatwo dodać do VCS.Rozważmy konwersję obiektów z bazy danych na pliki na kilku przykładach:
Typ obiektu
Ścieżka względna do pliku
Schemat
Nazwa
Tabela
accounts
public
./public/tables/accounts.txt
Procedura składowana
auth(hash bigint)
public
./public/functions/auth(int8).sql
booking
Reprezentacja
tariffs
./booking/views/tariffs.txt
Zawartość plików to tekstowa reprezentacja struktury konkretnego obiektu bazy danych. Na przykład, dla procedur składowanych zawartość pliku będzie pełną definicją procedury składowanej, zaczynającą się od bloku
CREATE OR REPLACE FUNCTION Jak widać z powyższej tabeli, ścieżka do pliku zawiera informacje o typie, schemacie i nazwie obiektu. Takie podejście ułatwia nawigację po zrzucie oraz przegląd zmian w bazie danych..
.sql
Rozszerzenie
.sqldla plików z kodem źródłowym procedur przechowywanych, wybrano, aby IDE automatycznie dostarczały narzędzia do interakcji z bazą danych przy otwieraniu pliku.
Jak przenosić zmiany w strukturze bazy danych na inne środowiska bez konfliktów i gigantycznych plików migracji
Zapisując zrzut bieżącej struktury bazy danych w VCS, uzyskujemy możliwość sprawdzenia, czy wprowadzano zmiany w strukturze bazy po utworzeniu zrzutu. W bibliotece w celu wykrycia zmian struktury bazy danych przewidziana jest funkcja verifyDump, która bez efektów ubocznych zwraca informacje o różnicach.
Alternatywny sposób sprawdzenia polega na ponownym wywołaniu funkcji , która zapisuje strukturę wszystkich obiektów z bazy danych w postaci osobnych plików tekstowych. Na wyjściu tworzony jest katalog zawierający strukturę bazy danych, podzieloną na pogrupowane pliki, które łatwo dodać do VCS., wskazując tę samą katalog, i sprawdzeniu w VCS obecności zmian. Ponieważ wszystkie obiekty z bazy danych są zapisane w osobnych plikach, VCS pokaże tylko zmienione obiekty.
Główną wadą tego sposobu jest konieczność nadpisania plików, aby zobaczyć zmiany.
Jak zorganizować proces równoległej pracy nad projektem kilku deweloperów
Dzięki funkcji deployDump kod źródłowy procedur przechowywanych można edytować w taki sam sposób jak zwykły kod aplikacji. Można dodawać/usuwać nowe linie w kodzie procedur przechowywanych i natychmiast przesyłać zmiany do systemu kontroli wersji lub tworzyć/usuwać procedury przechowywane, tworząc/usuwając odpowiednie pliki w katalogu ze zrzutem.
Na przykład, aby utworzyć nową procedurę przechowywaną w schemacie public , wystarczy stworzyć nowy plik z rozszerzeniem .sql w katalogu public/functions, umieścić w nim kod źródłowy procedury przechowywanej, w tym blok Jak widać z powyższej tabeli, ścieżka do pliku zawiera informacje o typie, schemacie i nazwie obiektu. Takie podejście ułatwia nawigację po zrzucie oraz przegląd zmian w bazie danych., a następnie wywołać funkcję deployDump. Podobnie odbywa się modyfikacja i usuwanie procedur przechowywanych. W ten sposób kod trafia jednocześnie do VCS i do bazy danych.
Jeśli w kodzie źródłowym jakiejkolwiek procedury przechowywanej wystąpi błąd, lub niezgodność między nazwą pliku a procedurą przechowywaną, to deployDump nie zostanie wykonana, wyświetlając komunikat o błędzie. Niespójność procedur przechowywanych między zrzutem a bieżącą bazą danych jest niemożliwa przy użyciu deployDump.
Podczas tworzenia nowej procedury przechowywanej nie ma potrzeby ręcznego wprowadzania poprawnej nazwy pliku. Wystarczy, że plik ma rozszerzenie
.sql. Po wywołaniudeployDumptekst błędu będzie zawierał poprawną nazwę, którą można wykorzystać do zmiany nazwy pliku.
deployDump pozwala zmieniać parametry funkcji lub typ zwracany bez dodatkowych działań, podczas gdy w klasycznym podejściu należałoby
najpierw wykonać DROP FUNCTION, a dopiero potem Jak widać z powyższej tabeli, ścieżka do pliku zawiera informacje o typie, schemacie i nazwie obiektu. Takie podejście ułatwia nawigację po zrzucie oraz przegląd zmian w bazie danych..
Niestety, istnieją sytuacje, w których deployDump nie można automatycznie zastosować zmian. Na przykład, jeśli usunięta zostanie funkcja wyzwalająca, która jest używana przez przynajmniej jeden wyzwalacz. Takie sytuacje wymagają ręcznego rozwiązania za pomocą plików migracji.
Jeśli za przenoszenie zmian w procedurach składowych odpowiada , to do przeniesienia pozostałych zmian w strukturze konieczne jest wykorzystanie plików migracji. Na przykład, dobrą biblioteką do pracy z migracjami jest .
Migracje powinny być stosowane przed uruchomieniem deployDump. Umożliwia to wprowadzenie wszystkich zmian w strukturze i rozwiązanie problematycznych sytuacji, aby zmiany w procedurach składowych później przeszły bez problemów.
Szczegółowe informacje na temat pracy z migracjami będą opisane w kolejnych rozdziałach.
Jak bezpiecznie wprowadzać większą ilość zmian w strukturze bazy danych na środowisko produkcyjne
Należy utworzyć skrypt pełnej inicjalizacji bazy danych, który będzie uruchamiany przez programistę na jego lokalnej maszynie, dostosowując strukturę lokalnej bazy danych do zapisanej w VCS zrzutu. Najłatwiej jest podzielić inicjalizację lokalnej bazy danych na 3 kroki:
- Import pliku z podstawową strukturą, który będzie nazywał się na przykład
base.sql - Zastosowanie migracji
- Wywołanie
deployDump
base.sql— to punkt wyjścia, na którym stosowane są migracje i wykonywanedeployDump, czylibase.sql + migracje + deployDump = aktualna struktura bazy danych. Taki plik można wygenerować za pomocą narzędziapg_dump. Używane jestbase.sqlwyłącznie przy inicjalizacji bazy danych od zera.
Nazwijmy skrypt pełnej inicjalizacji bazy danych refresh.sh. Proces roboczy może wyglądać następująco:
- Programista uruchamia w swoim środowisku
refresh.shi otrzymuje aktualną strukturę bazy danych - Programista zaczyna pracę nad zadaniem, modyfikując lokalną bazę danych zgodnie z potrzebami nowej funkcjonalności (
ALTER TABLE ... ADD COLUMNitd.) - Po zakończeniu zadania programista wywołuje funkcję
, która zapisuje strukturę wszystkich obiektów z bazy danych w postaci osobnych plików tekstowych. Na wyjściu tworzony jest katalog zawierający strukturę bazy danych, podzieloną na pogrupowane pliki, które łatwo dodać do VCS., aby zarejestrować w VCS zmiany dokonane w bazie danych - Programista ponownie uruchamia
refresh.sh, następnieverifyDump, który teraz pokazuje listę zmian do uwzględnienia w migracji - Programista przenosi wszystkie zmiany strukturalne do pliku migracji, uruchamia jeszcze raz
refresh.shiverifyDump, a jeśli migracja zostanie poprawnie utworzona,verifyDumppokaże brak różnic między lokalną bazą danych a zapisanym zrzutem.
Opisana wyżej procedura jest zgodna z zasadami gitflow. Każda gałąź w VCS będzie zawierać swoją wersję dumpa, a podczas scalania gałęzi nastąpi scalanie dumpów. W większości przypadków po scaleniu nie trzeba podejmować żadnych dodatkowych działań, ale jeżeli w różnych gałęziach wprowadzono zmiany, na przykład w tej samej tabeli, może wystąpić konflikt.
Rozważmy konfliktową sytuację na przykładzie: jest gałąź develop, od której odgałęziły się dwie gałęzie: feature1 i feature2, które nie mają konfliktów z develop, ale mają konflikty między sobą. Zadaniem jest wykonanie scalania obu gałęzi w develop. W takim przypadku zaleca się najpierw scalić jedną z gałęzi w develop, a następnie scalić develop do pozostałej gałęzi, rozwiązując przy tym konflikty w pozostałej gałęzi, a następnie wykonać scalanie ostatniej gałęzi w develop. Na etapie rozwiązywania konfliktów może być konieczne poprawienie pliku migracji w ostatniej gałęzi, aby odpowiadał on ostatecznemu dumpowi, który uwzględnia wyniki scalenia.
SchemaKeeper
Dzięki obecności w VCS dumpa aktualnej struktury bazy danych istnieje możliwość sprawdzenia bazy produkcyjnej pod kątem dokładnego dopasowania do wymaganej struktury. Gwarantuje to, że wszystkie zmiany, które zaplanowali deweloperzy, zostały pomyślnie przeniesione na bazę produkcyjną.
Ponieważ w PostgreSQL jest , zaleca się stosowanie następującej kolejności wdrożenia, aby w przypadku nieprzewidzianego błędu, "bezboleśnie" wykonać ROLLBACK:
- Rozpocznij transakcję
- W transakcji wykonaj wszystkie migracje
- W tej samej transakcji wykonaj
deployDump - Nie kończąc transakcji, wykonaj
verifyDump. Jeśli nie ma błędów, wykonajCOMMIT. Jeśli są błędy, wykonajROLLBACK
Te kroki są wystarczająco łatwe do włączenia w istniejące podejścia do wdrażania aplikacji, w tym zero-downtime.
Podsumowanie
Dzięki opisanym powyżej metodom można wycisnąć maksimum wydajności z projektów "PHP + PostgreSQL", poświęcając przy tym stosunkowo niewielką ilość wygody programowania w porównaniu z wdrożeniem całej logiki biznesowej w podstawowym kodzie aplikacji. Co więcej, przetwarzanie danych w często wygląda bardziej przejrzyście i wymaga mniejszej ilości kodu niż ta sama funkcjonalność napisana w PHP.
Źródło: habr.com
