Mechanizmy śledzenia zmian schematu bazy danych [zamknięte]

135

Jakie są najlepsze metody śledzenia i / lub automatyzacji zmian schematu bazy danych? Nasz zespół używa Subversion do kontroli wersji i byliśmy w stanie zautomatyzować niektóre z naszych zadań w ten sposób (wysyłanie kompilacji na serwer pomostowy, wdrażanie przetestowanego kodu na serwerze produkcyjnym), ale nadal aktualizujemy bazy danych ręcznie. Chciałbym znaleźć lub stworzyć rozwiązanie, które pozwoli nam wydajnie pracować na serwerach z różnymi środowiskami, jednocześnie nadal używając Subversion jako zaplecza, przez które aktualizacje kodu i bazy danych są przesyłane na różne serwery.

Wiele popularnych pakietów oprogramowania zawiera skrypty automatycznej aktualizacji, które wykrywają wersję bazy danych i wprowadzają niezbędne zmiany. Czy to najlepszy sposób na zrobienie tego nawet na większą skalę (w wielu projektach, a czasem w wielu środowiskach i językach)? Jeśli tak, to czy istnieje kod, który upraszcza ten proces, czy też najlepiej jest po prostu wprowadzić własne rozwiązanie? Czy ktoś wcześniej zaimplementował coś podobnego i zintegrował to z punktami przechwytującymi Subversion po zatwierdzeniu, czy to zły pomysł?

Chociaż preferowane byłoby rozwiązanie obsługujące wiele platform, zdecydowanie musimy obsługiwać stos Linux / Apache / MySQL / PHP, ponieważ większość naszej pracy odbywa się na tej platformie.

pix0r
źródło

Odpowiedzi:

56

W świecie Railsów istnieje koncepcja migracji, skryptów, w których zmiany w bazie danych są dokonywane w języku Ruby, a nie w specyficznym dla bazy danych stylu SQL. Twój kod migracji do Ruby jest konwertowany do DDL specyficznego dla Twojej bieżącej bazy danych; To sprawia, że ​​przełączanie platform baz danych jest bardzo łatwe.

Dla każdej zmiany wprowadzonej w bazie danych piszesz nową migrację. Migracje zazwyczaj mają dwie metody: metodę „w górę”, w której zmiany są stosowane, oraz metodę „w dół”, w której zmiany są cofane. Pojedyncze polecenie aktualizuje bazę danych i może być również użyte do przeniesienia bazy danych do określonej wersji schematu. W Railsach migracje są przechowywane we własnym katalogu w katalogu projektu i są sprawdzane pod kontrolą wersji, tak jak każdy inny kod projektu.

Ten przewodnik Oracle dotyczący migracji Railsów całkiem dobrze opisuje migracje.

Programiści używający innych języków przyjrzeli się migracjom i zaimplementowali własne wersje językowe. Wiem o Ruckusing , systemie migracji PHP, który jest wzorowany na migracji Railsów; to może być to, czego szukasz.

Joey deVilla
źródło
1
Ruckusing FTW - dostosowaliśmy go do naszego systemu db i jesteśmy z niego całkiem zadowoleni.
Piskvor opuścił budynek
Teraz znajduje się na github: github.com/ruckus/ruckusing-migrations
50

Używamy czegoś podobnego do bcwoord, aby zsynchronizować nasze schematy bazy danych między 5 różnymi instalacjami (produkcyjnymi, przejściowymi i kilkoma instalacjami programistycznymi) oraz tworzyć kopie zapasowe w kontroli wersji i działa całkiem dobrze. Opowiem trochę:


Aby zsynchronizować strukturę bazy danych, mamy jeden skrypt, update.php i kilka plików o numerach 1.sql, 2.sql, 3.sql itd. Skrypt używa dodatkowej tabeli do przechowywania aktualnego numeru wersji Baza danych. Pliki N.sql są tworzone ręcznie, aby przejść z wersji (N-1) do wersji N bazy danych.

Mogą być używane do dodawania tabel, dodawania kolumn, migracji danych ze starego do nowego formatu kolumny, a następnie upuszczania kolumny, wstawiania "głównych" wierszy danych, takich jak typy użytkowników, itp. W zasadzie może zrobić wszystko i przy odpowiednich danych skrypty migracji nigdy nie stracisz danych.

Skrypt aktualizacji działa w następujący sposób:

  • Połącz się z bazą danych.
  • Zrób kopię zapasową bieżącej bazy danych (ponieważ materiał będzie pomylić) [mysqldump].
  • Utwórz tabelę księgową (zwaną _meta), jeśli nie istnieje.
  • Przeczytaj aktualną WERSJĘ z tabeli _meta. Załóż 0, jeśli nie zostanie znaleziony.
  • Dla wszystkich plików .sql o numerach wyższych niż WERSJA, wykonaj je po kolei
  • Jeśli jeden z plików spowodował błąd: przywróć kopię zapasową
  • W przeciwnym razie zaktualizuj wersję w tabeli księgowej do najwyższego wykonanego pliku .sql.

Wszystko podlega kontroli źródła, a każda instalacja zawiera skrypt do aktualizacji do najnowszej wersji za pomocą jednego wykonania skryptu (wywołanie update.php z odpowiednim hasłem do bazy danych itp.). SVN aktualizuje środowiska pomostowe i produkcyjne za pomocą skryptu, który automatycznie wywołuje skrypt aktualizacji bazy danych, więc aktualizacja kodu obejmuje niezbędne aktualizacje bazy danych.

Możemy również użyć tego samego skryptu do odtworzenia całej bazy danych od podstaw; po prostu upuszczamy i ponownie tworzymy bazę danych, a następnie uruchamiamy skrypt, który całkowicie zapełni bazę danych. Możemy również użyć skryptu do wypełnienia pustej bazy danych w celu automatycznego testowania.


Skonfigurowanie tego systemu zajęło tylko kilka godzin, jest koncepcyjnie prosty i każdy otrzymuje schemat numerowania wersji, a możliwość rozwijania projektu bazy danych bez konieczności komunikowania się lub ręcznego wykonywania modyfikacji była nieoceniona. we wszystkich bazach danych.

Uważaj jednak podczas wklejania zapytań z phpMyAdmin! Te wygenerowane zapytania zwykle zawierają nazwę bazy danych, której na pewno nie chcesz, ponieważ spowoduje to uszkodzenie skryptów! Coś w rodzaju CREATE TABLE mydb. newtable(...) zakończy się niepowodzeniem, jeśli baza danych w systemie nie nosi nazwy mydb. Stworzyliśmy hak SVN przed komentarzem, który nie zezwala na pliki .sql zawierające mydbciąg znaków, co jest pewnym znakiem, że ktoś skopiował / wkleił z phpMyAdmina bez odpowiedniego sprawdzenia.

rix0rrr
źródło
Jak poradziłeś sobie z kolizjami? Wielu programistów zmienia ten sam element w bazie danych, na przykład procedurę składowaną? Może się tak zdarzyć, jeśli pracujesz w tej samej branży w tej samej branży lub masz dwie linie rozwoju (dwie gałęzie)
Asaf Mesika
Zderzenia były bardzo rzadkie; jedyną rzeczą, która się naprawdę wydarzyła, jest to, że dwie osoby próbowałyby utworzyć ten sam plik N.sql. Oczywiście pierwszy wygrywa, a drugi jest zmuszony zmienić nazwę na następną najwyższą liczbę i spróbować ponownie. Nie mieliśmy jednak wersji bazy danych w gałęzi.
rix0rrr
12

Mój zespół wykrywa wszystkie zmiany w bazie danych i przesyła te skrypty do SVN, wraz z każdym wydaniem aplikacji. Pozwala to na przyrostowe zmiany w bazie danych, bez utraty danych.

Aby przejść z jednej wersji do drugiej, wystarczy uruchomić zestaw skryptów zmian, a Twoja baza danych jest aktualna i nadal masz wszystkie swoje dane. Może nie jest to najłatwiejsza metoda, ale na pewno jest skuteczna.

Brandon Wood
źródło
1
jak zapisujesz wszystkie zmiany?
Smith
10

Problem tutaj naprawdę ułatwia programistom tworzenie skryptów własnych lokalnych zmian w kontroli źródła w celu udostępnienia ich zespołowi. Od wielu lat mam do czynienia z tym problemem i zainspirowała mnie funkcjonalność programu Visual Studio for Database. Jeśli potrzebujesz narzędzia open source z tymi samymi funkcjami, wypróbuj to: http://dbsourcetools.codeplex.com/ Baw się dobrze, - Nathan.


źródło
10

Jeśli nadal szukasz rozwiązań: proponujemy narzędzie o nazwie neXtep designer. Jest to środowisko programistyczne dla baz danych, za pomocą którego można umieścić całą bazę danych pod kontrolą wersji. Pracujesz na repozytorium z kontrolą wersji, w którym można śledzić każdą zmianę.

Gdy zajdzie potrzeba wydania aktualizacji, można zatwierdzić komponenty, a produkt automatycznie wygeneruje skrypt aktualizacji SQL z poprzedniej wersji. Oczywiście możesz wygenerować ten kod SQL z dowolnych 2 wersji.

Następnie masz wiele opcji: możesz wziąć te skrypty i umieścić je w swoim SVN z kodem aplikacji, aby zostały wdrożone przez istniejący mechanizm. Inną opcją jest użycie mechanizmu dostarczania neXtep: skrypty są eksportowane w czymś zwanym „pakietem dostarczania” (skrypty SQL + deskryptor XML), a instalator może zrozumieć ten pakiet i wdrożyć go na serwerze docelowym, zapewniając jednocześnie spójność strukturalną, zależność sprawdzić, zarejestrować zainstalowaną wersję itp.

Produkt jest objęty licencją GPL i jest oparty na Eclipse, więc działa na systemach Linux, Mac i Windows. Obecnie obsługuje również Oracle, Mysql i Postgresql (wsparcie dla DB2 jest w drodze). Zajrzyj na wiki, na którym znajdziesz bardziej szczegółowe informacje: http://www.nextep-softwares.com/wiki

Christophe Fondacci
źródło
Wygląda ciekawie. Czy ma również interfejs wiersza poleceń, czy jest planowany?
Piskvor opuścił budynek
8

Scott Ambler tworzy wielką serię artykułów (i jest współautorem książki ) na temat refaktoryzacji baz danych, z myślą, że powinieneś zasadniczo stosować zasady i praktyki TDD, aby utrzymać swój schemat. Skonfigurujesz serię testów jednostek danych struktury i inicjatora dla bazy danych. Następnie, zanim cokolwiek zmienisz, modyfikujesz / piszesz testy, aby odzwierciedlić tę zmianę.

Robimy to już od jakiegoś czasu i wydaje się, że działa. Napisaliśmy kod do generowania podstawowych kontroli nazw kolumn i typów danych w zestawie testów jednostkowych. W dowolnym momencie możemy ponownie przeprowadzić te testy, aby sprawdzić, czy baza danych w sekcji SVN jest zgodna z aktualną bazą danych, z której faktycznie działa aplikacja.

Jak się okazuje, programiści czasami modyfikują swoją bazę danych piaskownicy i zaniedbują aktualizację pliku schematu w SVN. Kod zależy zatem od zmiany bazy danych, która nie została wpisana. Tego rodzaju błąd może być nieznośnie trudny do ustalenia, ale zestaw testów wykryje go od razu. Jest to szczególnie przyjemne, jeśli masz to wbudowane w większy plan ciągłej integracji.

Sam McAfee
źródło
7

Zrzuć schemat do pliku i dodaj go do kontroli źródła. Następnie prosta różnica pokaże, co się zmieniło.

deadprogrammer
źródło
1
Zrzut musi być w języku SQL, podobnie jak mysqldump, zrzuty Oracle są binarne.
Osama Al-Maadeed
7
Istnieje również bardziej podstawowy problem związany z różnicowaniem schematów. Jak odróżnić upuszczanie i dodawanie kolumny od zmiany nazwy kolumny. Odpowiedź jest prosta: nie możesz. To jest powód, dla którego musisz zarejestrować rzeczywiste operacje zmiany schematu.
psp
Różnica pokaże, że jedna kolumna zniknęła, podczas gdy pojawiła się druga (chyba że mają taką samą nazwę), iw większości przypadków wystarczy. Skryptowanie każdej zmiany schematu jest oczywiście dobrym sposobem: na przykład w Drupalu jest to obsługiwane przez specjalny punkt zaczepienia.
deadprogrammer
5

To trochę mało zaawansowana technologia i może być lepsze rozwiązanie, ale możesz po prostu przechowywać swój schemat w skrypcie SQL, który można uruchomić w celu utworzenia bazy danych. Myślę, że możesz wykonać polecenie, aby wygenerować ten skrypt, ale niestety nie znam polecenia.

Następnie zatwierdź skrypt w kontroli źródła wraz z kodem, który na nim działa. Gdy zajdzie potrzeba zmiany schematu wraz z kodem, skrypt może zostać zaewidencjonowany razem z kodem wymagającym zmienionego schematu. Następnie różnice w skrypcie będą wskazywać różnice przy zmianach schematu.

Za pomocą tego skryptu możesz zintegrować go z DBUnit lub jakimś rodzajem skryptu kompilacji, więc wydaje się, że pasuje do już zautomatyzowanych procesów.

Mike Stone
źródło
Tak, właśnie to mamy teraz na miejscu. Niestety nie daje nam to łatwego sposobu na modyfikację istniejących baz danych - skrypt SQL wygenerowany przez mysqldump zakłada, że ​​tworzysz tabelę od zera (lub nadpisujesz tabelę, jeśli istnieje). Potrzebujemy czegoś bardziej zaawansowanego technologicznie, ponieważ musi zastosować sekwencję instrukcji ALTER TABLE do bazy danych, a aby to zrobić poprawnie, musi być świadomy aktualnego stanu bazy danych.
pix0r
5

Jeśli używasz C #, spójrz na Subsonic, bardzo przydatne narzędzie ORM, ale generuje również skrypt sql do odtworzenia schematu i \ lub danych. Te skrypty można następnie umieścić w kontroli źródła.

http://subsonicproject.com/

Dan
źródło
Wydaje się, że w tym momencie jest martwym adresem URL.
Mark Schultheiss,
5

Użyłem następującej struktury projektu bazy danych w Visual Studio dla kilku projektów i działało całkiem dobrze:

Baza danych

Zmień skrypty

0.PreDeploy.sql

1.SchemaChanges.sql

2.DataChanges.sql

3.Permissions.sql

Twórz skrypty

Sprocs

Funkcje

Wyświetlenia

Nasz system kompilacji aktualizuje bazę danych z jednej wersji do drugiej, wykonując skrypty w następującej kolejności:

1.PreDeploy.sql

2.SchemaChanges.sql

Zawartość folderu Create Scripts

2.DataChanges.sql

3.Permissions.sql

Każdy programista sprawdza swoje zmiany pod kątem określonego błędu / funkcji, dołączając swój kod na końcu każdego pliku. Gdy wersja główna jest kompletna i rozgałęziona w kontroli źródła, zawartość plików .sql w folderze Change Scripts jest usuwana.

tbreffni
źródło
5

Stosujemy bardzo proste, ale skuteczne rozwiązanie.

W przypadku nowych instalacji mamy w repozytorium plik metadata.sql, który zawiera cały schemat bazy danych, a następnie w procesie budowania używamy tego pliku do generowania bazy danych.

W przypadku aktualizacji dodajemy aktualizacje w oprogramowaniu zakodowanym na stałe. Utrzymujemy to na stałe, ponieważ nie lubimy rozwiązywać problemów, zanim to naprawdę JEST problem, a tego typu rzeczy do tej pory nie okazały się problemem.

Więc w naszym oprogramowaniu mamy coś takiego:

RegisterUpgrade(1, 'ALTER TABLE XX ADD XY CHAR(1) NOT NULL;');

Ten kod sprawdzi, czy baza danych jest w wersji 1 (która jest przechowywana w tabeli utworzonej automatycznie), jeśli jest nieaktualna, to polecenie jest wykonywane.

Aby zaktualizować plik metadata.sql w repozytorium, uruchamiamy te aktualizacje lokalnie, a następnie wyodrębniamy pełne metadane bazy danych.

Jedyną rzeczą, która zdarza się często, jest zapomnienie o zatwierdzeniu pliku metadata.sql, ale nie jest to poważny problem, ponieważ jest łatwy do przetestowania w procesie kompilacji, a jedyną rzeczą, która może się zdarzyć, jest wykonanie nowej instalacji za pomocą przestarzała baza danych i zaktualizowana przy pierwszym użyciu.

Nie obsługujemy również obniżania wersji, ale jest to zgodne z projektem, jeśli coś zepsuje się podczas aktualizacji, przywróciliśmy poprzednią wersję i naprawiliśmy aktualizację przed ponowną próbą.

Fabio Gomes
źródło
4

Tworzę foldery nazwane na podstawie wersji kompilacji i umieszczam w nich skrypty aktualizacji i obniżenia wersji. Na przykład możesz mieć następujące foldery: 1.0.0, 1.0.1 i 1.0.2. Każdy z nich zawiera skrypt, który umożliwia aktualizację lub obniżenie wersji bazy danych między wersjami.

Jeśli klient lub klient zadzwoni do Ciebie z problemem z wersją 1.0.1, a używasz 1.0.2, przywrócenie bazy danych z powrotem do jego wersji nie będzie problemem.

W swojej bazie danych utwórz tabelę o nazwie „schemat”, w której umieścisz aktualną wersję bazy danych. Wtedy łatwo jest napisać program, który może zaktualizować lub obniżyć wersję bazy danych.

Tak jak powiedział Joey, jeśli jesteś w świecie Railsów, użyj migracji. :)

Louis Salin
źródło
3

W moim obecnym projekcie PHP korzystamy z idei migracji railsów i mamy katalog migracji, w którym przechowujemy pliki o tytule „migracja_XX.sql”, gdzie XX to numer migracji. Obecnie pliki te są tworzone ręcznie w miarę dokonywania aktualizacji, ale ich tworzenie można łatwo modyfikować.

Następnie mamy skrypt o nazwie „Migration_watcher”, który, tak jak jesteśmy w wersji pre-alpha, jest obecnie uruchamiany przy każdym ładowaniu strony i sprawdza, czy istnieje nowy plik migracyjny_XX.sql, w którym XX jest większy niż bieżąca wersja migracji. Jeśli tak, to uruchamia wszystkie pliki migracji_XX.sql do największej liczby w bazie danych i voila! zmiany schematu są zautomatyzowane.

Jeśli potrzebujesz możliwości przywrócenia systemu, wymagałoby to wielu poprawek, ale jest to proste i działa bardzo dobrze dla naszego dość małego zespołu do tej pory.

Eric Scrivner
źródło
3

Zalecałbym używanie Ant (międzyplatformowego) do obsługi skryptów (ponieważ może on praktycznie komunikować się z każdą bazą danych przez jdbc) i Subversion dla repozytorium źródłowego. Ant pozwoli ci "zarchiwizować" twoją bazę danych w lokalnych plikach przed wprowadzeniem zmian. 1. wykonaj kopię zapasową istniejącego schematu db do pliku za pośrednictwem Ant 2. kontrolę wersji do repozytorium Subversion za pośrednictwem Ant 3. wyślij nowe instrukcje sql do db przez Ant

Cruz
źródło
3

Toad for MySQL ma funkcję o nazwie porównywanie schematów, która umożliwia synchronizację 2 baz danych. To najlepsze narzędzie, jakiego do tej pory używałem.

Petah
źródło
3

Podoba mi się sposób, w jaki Yii obsługuje migracje baz danych. Migracja to po prostu implementacja skryptu PHP CDbMigration. CDbMigrationdefiniuje upmetodę, która zawiera logikę migracji. Możliwe jest również zaimplementowanie downmetody wspierającej odwrócenie migracji. Alternatywnie safeUplub safeDownmożna go użyć, aby upewnić się, że migracja jest wykonywana w kontekście transakcji.

Narzędzie wiersza poleceń Yii yiicobsługuje tworzenie i wykonywanie migracji. Migracje można stosować lub cofać, pojedynczo lub partiami. Utworzenie migracji skutkuje powstaniem kodu implementującej klasy PHP o CDbMigrationunikalnej nazwie na podstawie sygnatury czasowej i nazwy migracji określonej przez użytkownika. Wszystkie migracje, które zostały wcześniej zastosowane do bazy danych, są przechowywane w tabeli migracji.

Aby uzyskać więcej informacji, zobacz artykuł dotyczący migracji bazy danych w podręczniku.

Ton van den Heuvel
źródło
2

Migracje IMHO mają ogromny problem:

Aktualizacja z jednej wersji do drugiej działa dobrze, ale wykonanie nowej instalacji danej wersji może zająć wieczność, jeśli masz setki tabel i długą historię zmian (tak jak my).

Uruchomienie całej historii delt od linii bazowej do aktualnej wersji (dla setek baz danych klientów) może zająć bardzo dużo czasu.

Edson Medina
źródło
0

Istnieje narzędzie mysql-diff z wiersza poleceń, które porównuje schematy bazy danych, gdzie schemat może być aktywną bazą danych lub skryptem SQL na dysku. Jest to dobre rozwiązanie dla większości zadań migracji schematu.

stepancheg
źródło