Przejdź do treści

Migracja systemowych zmian BD

Informacje dla użytkowników technologii NEOS

W wersji 4.6 serwer NEOS otrzymał dodatkową funkcjonalność migracji bazodanowych. Jest to mechanizm, który dba o to aby struktury bazodanowe były aktualne dla uruchomionej wersji serwera. Przy starcie NEOS weryfikuje czy domyślna baza danych ma wszystkie potrzebne tabele oraz procedury w aktualnych wersjach. Użytkownik po uruchomieniu nowej wersji serwera NEOS zostanie poinformowany komunikatem o konieczności wgrania migracji bazodanowej. Po tej informacji należy wybrać "Wygeneruj skrypt" i wgrać ten skrypt na domyślną bazę danych. Po wgraniu skryptu ponownie weryfikujemy czy struktura bazy jest aktualna. Jeśli tak to możemy kontynuować pracę z nową wersją serwera NEOS.

Przykład wgrania migracji

  • Po podłączeniu i uruchomieniu serwera w nowej wersji automatycznie następuje sprawdzenie wersji metadanych. Jeśli mechanizm uzna, że struktura jest nie aktualna to poinformuje użytkownika w następujący sposób:
  • Gdy serwer jest uruchomiony jako aplikacja komunikat pojawi się w konsoli NEOSa

  • Niezależnie czy serwer jest uruchomiony jako usługa czy aplikacja to po zalogowaniu osoby z sente (SENTE=1) zostanie wyświetlony DebugLog z następującą informacją:

  • Uruchamiamy okno migracji. Konfiguracja -> NEOS -> Migracje.

  • Klikamy przycisk "Wygeneruj skrypt".

Okno z wygenerowanym skryptem.

  • Wgrywamy skrypt na domyślną bazę danych za pomocą IBExperta. Następnie klikamy przycisk "Sprawdź spójność BD". Baza danych powinna być spójna.

Uwaga

Jeśli mechanizm ten wykryje problemy oznacza to, że część struktur BD z konkretnej migracji znajduje się już na BD a pozostała część jest np. w starej wersji, lub nie ma ich wcale. W takim przypadku należy wygenerować i wgrać skrypt na BD a gdy będą błędy należy je przeanalizować.

Powyższy przykład na gif'ie.

Informacje dla developerów technologii NEOS

Założenia

  1. Silnik obsługuje tylko migracje przyrostowe
  2. Developer tworzący nową migrację musi być pewny, że starsze wersje serwera NEOS będą poprawnie działać po jego migracji. Może być sytuacja, że wersje 4.6 oraz 4.7 będą działać na jednej BD równolegle.
  3. Developer przygotowuje skrypt, który musi wgrywać się bez błędów. (Silnik migracji nie modyfikuje skryptów!!)
  4. Silnik obsługuje 2 warianty. Create - tworzenie nowych metadanych, Update - aktualizacja metadanych. Przy czym aktualizację wykorzystujemy tylko do: trigerów, procedur oraz widoków.
  5. Silnik rozpoznaje kolejne wersje, które są oznaczone do aktualizacji tylko po treści descriptiona. W descriptionie musi znajdować się symbol PRki lub BSa w ramach którego została ona zmodyfikowana. Description jest traktowany przyrostowo (na podstawie descriptiona NEOS określa czy dana migracja istnieje już na BD).
  6. Developer, który dodaje skrypt musi określić też checki dla swoich metadanych w skrypcie.
  7. Silnik wykrywa problematyczne migracje w momencie gdy w jednej migarcji zostaje zostaje wykryta co najmniej 1 metadana, która już istnieje w BD a pozostałe metadane nie są w odpowiedniej wersji. Skrypt z takiej migracji również zostanie wygenerowany
  8. Skrypty z migracji zostają połączone w kolejności dodawania migracji.
  9. Migracje są tworzone per feature. Zatem np. Scheduler to jest jeden feature w ramach, którego może być wiele migracji.
  10. Migracje mogą być tworzone w modułach. Po załadowaniu modułu NEOS wyszukuje w nich czy istnieją migracje.
  11. Mechanizm grupuje migracje po Modułach -> Nazwie feature.
  12. Silnik uruchamia weryfikację przy starcie NEOSa. Uruchamiana weryfikacja jest w osobnym tasku zatem nie wpływa ona na długość uruchamiania serwera.
  13. Należy pamiętać, aby przy dodawaniu nowych migracji zadbać o nadanie grantów dla obiektów, które edytujemy lub dodajemy.

Tworzenie migracji

  • Aby utworzyć nową migrację należy dodać klasę w projekcie w którym istnieje mechanizm wymagający konkretnych struktur bazodanowych. Migracje umieszczamy w folderze Migrations.
  • Klasę tworzymy per feature(funkcjonalność). Przykładowa powinna wyglądać następująco:
class ExampleMigrationFeature : MigrationFeatureAbstract
{
  public override string FeatureDescription
  {
    get
    {
      return "Opis funkcjonalności powinien być dłuższy";
    }
  }

  public override string FeatureName
  {
    get
    {
      return "Krótka nazwa funkcjonalności";
    }
  }

  public override DateTime FeatureCreationDate => new DateTime(2020, 6, 20); //Data utworzenia klasy dla danego Feature'a

  protected override void PopulateMigrations()
  {
    //Dodanie migracji oraz checkow
  }

  #region DDLs
  private const string DDL_MIG1 = @"DDL Script for migration1";
  #endregion
}
  • Klasa MigrationFeatureAbstract znajduje się w paczce Neos.Core.Interop od wersji 4.6

  • Tworzymy implementację metody dodającej migracje. W pierwszej kolejności wykonujemy metodę AddMigration(), która doda nam kolejną migrację. Następnie dodajemy checki, które powinny uwzględniać wszystkie zmiany metadanych jakie zawiera skrypt. Checki dodajemy metodą AddChange(#NazwaMetadanej#, #TypMetadanej#, #TrybZmiany#, #Sygnatura#). Dodajemy wszystkie checki dla zmian, które mamy w skrypcie. Ostatnim krokiem należy dodać utworzony skrypt za pomocą metody SetDDLScript(DDL_MIG1).

Uwaga

Tworząc skrypt sql, do wprowadzenia zmian bazodanowych, należy pamiętać o dodaniu frazy NEOSMIGRATION na początku Description-a, tak aby było wiadomo że w danej metadanej zmiany wprowadziła migracja.

Note

Należy zwrócić uwagę, że niektóre z migracji neosowych wykorzystują wczesniej już dodane mechanizmy. Od wersji 6.1 Neosa dodano propertę FeatureCreationDate. Jest ona używana w celu ustalenia kolejności, w jakiej mają zostac dodane skrypty z poszczególnych klas zawierających migracje. Jeżeli nie zostanie ona nadpisana, domyślna wartość to DateTime.MinValue.

Kod dodawania migracji może wyglądać następująco:

protected override void PopulateMigrations()
{
  //Dodanie migracji oraz checkow
  AddMigration()
    .AddChange("MY_TABLE", MetadataType.Table, MetadataMode.Create)
    .AddChange("MY_PROCEDURE", MetadataType.Procedure, MetadataMode.Create)
    .AddChange("MY_UPDATE_PROCEDURE", MetadataType.Procedure, MetadataMode.Update, "PR0002019")
    .SetDDLScript(DDL_MIG1);

  AddMigration()
    .AddChange("MY2_TABLE", MetadataType.Table, MetadataMode.Create)
    .SetDDLScript(DDL_MIG2);
}

Od wersji 5.3 Neos obsługuje pisanie migracji wraz z zapytaniem SQL

Od wersji 5.3 rozbudowano mechanizm tworzenia checkerów migracji o możliwość dodania własnego zapytania SQL. Zapytanie to gdy nie zwróci żadnych wartości (same nulle) to oznacza, iż należy wgrać tą migrację. Ważne aby skrypt migracji i zapytanie do weryfikacji były ze sobą spójne. Tzn, że po wgraniu skryptu zapytanie SQL zwróci jakiś rekord. Zapytanie do weryfikacji musi działać po indeksach !!! ponieważ przy każdym starcie NEOSa będzie ono uruchamiane na BD do której NEOS się połączy. Oczywiście jako developerzy musimy zadbać aby to zapytanie mogło się wykonać, czyli muszą istnieć struktury do którym zapytanie piszemy. Mechanizmem tym możemy wgrywać / aktualizować sekcje S_APPINI. Poniżej wzorcowy przykład:

protected override void PopulateMigrations()
{
  string sqlCheck = @"select first 1 1 from S_APPINI s 
                    where s.section = 'Action:ExecuteQueryFromNeos' 
                    and s.ident = 'Signature' 
                    and s.val containing ';TSU_278;'";

  AddMigration()
  .AddChangeWithSqlCheck("Action:ExecuteQueryFromNeos", sqlCheck)
  .SetDDLScript(Migration1DDL);
}

Uruchomienie skanowania modułów w celu wykrycia migracji

Aby autofac automatycznie skanował i wykrywał migracje utworzone w module należy podczas rejestracji modułu dodać następujący kod, który spowoduje, że autofac będzie skanował naszą DLLkę w celu zarejestrowania migracji z tego modułu:

protected override void Load(ContainerBuilder builder)
{
  var dataAccess = System.Reflection.Assembly.GetExecutingAssembly();
  builder.RegisterAssemblyTypes(dataAccess).As<IMigrationFeature>();
}