2014-07-09 7 views
8

Trochę skomplikowane do opisania, ale zrobię co w mojej mocy. Zasadniczo używamy przepływu pracy Git, co oznacza, że ​​mamy następujące oddziały:Jak obsługiwać wiele skryptów zmiany db pochodzących z różnych gałęzi funkcji Git?

  • produkcja, która jest branżą na żywo. Wszystko odbywa się w żywym środowisku sieciowym.
  • integracja, w której zintegrowana jest cała nowa funkcjonalność. Ten oddział jest co tydzień łączony z produkcją.
  • jedno lub więcej oddziałów funkcji, w których programiści lub zespoły programistów opracowują nowe funkcje. Po zakończeniu tego procesu programiści łączą swoją gałąź funkcji z integracją.

Nic tak naprawdę nie jest tutaj skomplikowane. Ale ponieważ nasza aplikacja jest aplikacją działającą na bazie MySQL, nowa funkcjonalność często wymaga zmian w schemacie bazy danych. Aby zautomatyzować to, używamy dbdeploy, który pozwala nam tworzyć skrypty zmian, podając liczbę. Na przykład. 00001.sql, 00002.sql, itp. Po połączeniu z gałęzią integracji, dbdeploy sprawdzi, które skrypty zmian mają numer wyższy niż ostatnio wykonany w tej konkretnej bazie danych, i wykona je.

Teraz należy przyjąć następujące. - integracja zawiera skrypty do 00200.sql. Wszystkie one są wykonywane w integracyjnej bazie danych. - programista John ma funkcję featureX, która została utworzona, gdy integracja nadal zawierała 00199.sql jako najwyższy skrypt zmian.

John tworzy 00200.sql z powodu pewnych wymaganych zmian schematu bazy danych.

Teraz, w pewnym momencie John połączy swoje modyfikacje z powrotem w gałęzi integracji. John dostanie konflikt łączący i zobaczy, że jego 00200.sql już istnieje w integracji. Oznacza to, że musi otworzyć plik będący w konflikcie, wyodrębnić jego zawartość, zresetować ten plik z powrotem do "kopalni" (stan oryginalny jak w integracji) i umieścić własną zawartość w nowym pliku.

Teraz, ponieważ pracujemy z dziesięcioma programistami, codziennie otrzymujemy tę sytuację. I chociaż rozumiemy powody tego, czasami jest to bardzo kłopotliwe. John zmienia nazwę swojego skryptu, scala się z integracją, przesuwa zmiany w górę, aby zobaczyć, że ktoś inny stworzył już 00201.sql, co wymaga od Johna powtórzenia procesu.

Na pewno musi być więcej zespołów korzystających z przepływu pracy Git i korzystanie z narzędzia do zarządzania zmianami bazy danych do automatyzacji zmian schematów bazy danych?

Więc, krótko mówiąc, moje pytania są następujące:

  • Jak zautomatyzować zmiany schematu bazy danych, podczas pracy na różnych oddziałach fabularnych, które działają na różnych instancji tego samego db?
  • Jak zapobiegać konflikty seryjne przez cały czas, nadal mając opcję ustalonej kolejności w wykonanych skryptach zmian? Na przykład. 00199.sql musi być wykonane przed 00200.sql, ponieważ 00200.sql może zależeć od czegoś wykonanego w 00199.sql.

Wszelkie inne wskazówki są mile widziane.

+0

Przydatna i podchwytliwa dyskusja, na pewno. Deweloperzy oprogramowania, zauważcie. Śledzenie zmian schematów, o czym świadczy OP, naprawdę zależy od tego, jakiego rodzaju zasięg oczekuje się od wysiłku w pierwszej kolejności. Chcesz mieć codzienną kompilację? Wersja? Punkty odzyskiwania? Kodowanie obronne? Rozwiązania będą się różnić w wyniku. –

Odpowiedz

0

Użyłem dwóch różnych sposobów podejścia do rozwiązania problemu w przeszłości.

Po pierwsze należy użyć n ORM, które może obsłużyć aktualizacje schematu.

Innym rozwiązaniem jest utworzenie skryptu, który stopniowo buduje schemat bazy danych. W ten sposób, jeśli deweloper potrzebuje dodatkowego wiersza w tabeli, powinien dodać odpowiednią instrukcję SQL po utworzeniu tabeli. Podobnie, jeśli potrzebuje nowej tabeli, powinien dodać do tego instrukcję sql. Następnie łączenie staje się kwestią upewnienia się, że wszystko dzieje się we właściwej kolejności. Jest to zasadniczo to, co robi proces aktualizacji bazy danych w ORM. Taki skrypt musi być kodowany bardzo defensywnie, a każde stwierdzenie powinno sprawdzać, czy istnieje jego perquisites.

4

Szyny używane do tego, z dokładnie opisanymi problemami. Zmienili z następującym schematem: Pliki są oznaczone znacznikiem czasu UTC, kiedy plik został stworzony (szyny nazywa ich migracje), np

20140723069701_add_foo_to_bar 

(Druga część nazwy nie przyczynia się do zamawiania).

Railsy rejestrują znaczniki czasu wszystkich przeprowadzonych migracji. Gdy poprosisz go o uruchomienie oczekujących migracji, wybierze wszystkie pliki migracji, których znacznik czasu nie znajduje się na liście już uruchomionych migracji, i uruchamia je w kolejności numerycznej.

Konflikty scalania nie będą już dostępne, chyba że dwie osoby utworzą je dokładnie w tym samym momencie.

Pliki nadal są wykonywane w kolejności, w jakiej zostały napisane, ale prawdopodobnie przeplatane cudzym dziełem. Teoretycznie nadal możesz mieć problemy - np. Programista decyduje się zmienić nazwę tabeli, że zdecydowałem się również dodać kolumnę. Jest to o wiele mniej powszechne niż 2 deweloperów, którzy wprowadzają jakiekolwiek zmiany w db, a będziesz mieć problemy, nawet jeśli nie uwzględnisz zmian schematu, prawdopodobnie właśnie napisałem kod, który zapytuje o tabelę, która już nie istnieje - w pewnym momencie programiści pracujący nad podobnymi rzeczami będą mieli rozmawiać ze sobą!

2

Kilka sugestii:

1 - spojrzeć na Liquibase każda wersja pobiera plik, który odwołuje się do zmian, które muszą się zdarzyć, pliki zmiana może być nazwany przy użyciu znaczący ciąg zamiast liczby.

2 - mają centralną lokalizację do uzyskania następnego dostępnego numeru, następnie ludzie używają najnowszego numeru.

Użyłem Liquibase w przeszłości, całkiem pomyślnie i nie mieliśmy problemu, który opisałeś.

+0

Ale czy używałeś również przepływu pracy GIT z oddziałami funkcji dla każdego programisty? Ponieważ, szczególnie przy opcji 2, zakładam, że nadal masz problemy z gwarantowaną kolejnością wykonania we wszystkich oddziałach. Na przykład. John wziąłby numer 3, ponieważ wziąłem numer 2. Ale John połączy swoje zmiany w branży integracyjnej przede mną. W ten sposób zmiany Johna zostaną wykonane przed moim w branży integracyjnej. Później, po połączeniu z produkcją, moje zmiany zostaną wykonane przed Johns. –

+0

Nigdy nie korzystałem w ogóle z opcji 2, to najlepsze, co mogłem wymyślić w przypadku narzędzia do zarządzania schematem, które używa ponumerowanych nazw skryptów. Użyłem oddziałów funkcji z Liquibase, zarówno w wersji grupowej, jak i z ciągłym wdrażaniem i działało dobrze. Tory Liquibase, które zmieniły zestaw, zostały zastosowane i stosują te, których brakuje, a także wspierają zależności między zestawami zmian, pozwalając na wymuszone porządkowanie w razie potrzeby. –

1

Jako Frederick Cheung suggested używaj znaczników czasu zamiast numeru seryjnego. Stosowanie zmian schematu według kolejności datestamp powinno działać, ponieważ zmiany schematu mogą zależeć tylko od zmian wcześniejszej daty.

Ponadto należy podać nazwę programisty w nazwie skryptu zmian. Zapobiegnie to konfliktom łączącym w 100%.

Twój hak scalający powinien po prostu szukać nowo dodanych skryptów zmian (obecnych w połączonej gałęzi, ale nie w gałęzi źródłowej) i wykonywać je według kolejności znacznika czasu.

0

Dla dbvc commandline tool używam git log do ustalenia kolejności skryptów aktualizacji.

git log -c --no-merges --pretty="format:" --name-status -p dev/db/updates/ | \ 
    grep '^A' | awk '{print $2}' | tac 

W takim przypadku sposób kolejności zatwierdzeń określa kolejność, w której aktualizacje są uruchamiane. Które jest najbardziej prawdopodobne, czego chcesz.

  • Jeśli prowadzisz git merge b, aktualizacje z Master zostanie uruchomiony pierwszy i niż od B.
  • Jeśli prowadzisz git rebase b, aktualizacja z B będzie działać przede niż od pana.
Powiązane problemy