Skip to main content Link Menu Expand (external link) Document Search Copy Copied

Synchronizacja SQL

Podsumowanie:

Synchronizacja SQL to mechanizm cyklicznego importu danych organizacyjnych (użytkowników i jednostek organizacyjnych) z systemu źródłowego do nAxiom i ich aktualizacji. Umożliwia zsynchronizowanie struktury organizacyjnej w nAxiom z dowolnym systemem, z którego dane można wyeksportować do bazy danych SQL nAxiom. Proces obejmuje dwa etapy: import danych do tabel przejściowych oraz automatyczną aktualizację struktury docelowej.

Informacje o przebiegu synchronizacji są dostępne poprzez monitorowanie statusu synchronizacji tabel core.SyncUserProfiles i core.SyncOUInstances w tabeli core.SqlTableStatuses.

Czym jest synchronizacja SQL

Synchronizacja SQL jest uniwersalnym mechanizmem importu danych organizacyjnych z systemu źródłowego do nAxiom. W odróżnieniu od synchronizacji wbudowanej , która komunikuje się bezpośrednio z źródłem danych (AD, OpenLDAP), synchronizacja SQL polega na:

  1. Imporcie danych — wyeksportowanie informacji o użytkownikach i jednostkach organizacyjnych z systemu źródłowego do tabel przejściowych w bazie danych nAxiom
  2. Automatycznej synchronizacji — przetworzenie danych z tabel przejściowych i aktualizacja struktury organizacyjnej w nAxiom

Takie rozdzielenie pozwala na:

  • Elastyczne integracje z dowolnymi systemami źródłowymi
  • Przygotowanie i walidację danych przed synchronizacją
  • Zmianę trybu synchronizacji bez wpływu na proces importu
  • Łatwe debugowanie — dane z tabel przejściowych są dostępne dla administracji

Wymagania i przygotowanie

Dane niezbędne do synchronizacji

Synchronizacja wymaga następujących informacji dla każdego użytkownika:

  • Identyfikator użytkownika (login, ID z systemu źródłowego)
  • Imię i nazwisko (opcjonalnie rozdzielone na imię i nazwisko)
  • Adres e-mail
  • Przypisanie do jednostki organizacyjnej
  • Status (aktywny/nieaktywny)
  • Data wygaśnięcia profilu

Dla jednostek organizacyjnych:

  • Identyfikator OU (kod, ID z systemu źródłowego)
  • Identyfikator OU nadrzędnej (relacja hierarchiczna)
  • Kod
  • Nazwa
  • Status (aktywna/nieaktywna)
  • Data początkowa aktywności
  • Data końcowa aktywności

Przygotowanie danych

Dane z systemu źródłowego muszą być wyeksportowane w formacie, który można załadować do tabel synchronizacyjnych nAxiom. Typowym podejściem jest:

  • Eksport z systemu źródłowego do pliku CSV lub formatu tekstowego
  • Transformacja danych (jeśli wymagana) za pomocą skryptu lub narzędzia ETL
  • Załadowanie do tabel przejściowych (SyncUserProfiles, SyncOUInstances, SyncOUInstanceUsers) za pośrednictwem procedury SQL lub skryptu

Konfiguracja

Synchronizacja SQL jest sterowana przez konfigurację tenanta. W konfiguracji tenanta określa się między innymi:

  • tryb synchronizacji (SynchronizationType)
  • częstotliwość sprawdzania statusów (RepeatInterval)
  • domyślne wartości używane podczas synchronizacji, np. język, role i adres e-mail
  • dodatkowe opcje wpływające na sposób aktualizacji użytkowników i jednostek organizacyjnych

TaskService odczytuje te ustawienia z konfiguracji tenanta i na ich podstawie wykonuje cykliczną synchronizację.

Tabele synchronizacyjne

Dane przejściowe są przechowywane w czterech tabelach:

core.SyncUserProfiles — profile użytkowników

  • Id — unikalny identyfikator rekordu (auto-increment)
  • UserId (nvarchar, UNIQUE) — identyfikator użytkownika z systemu źródłowego (login, GUID itp.)
  • ParentId — FK do UserId (dla hierarchii, np. manager użytkownika)
  • UserName — nazwa użytkownika (login wyświetlany)
  • FirstName, LastName — imię i nazwisko
  • Email — adres e-mail
  • IsActive (bit) — czy użytkownik jest aktywny (1 = tak, 0 = nie)
  • ExpireDate (datetime2) — data wygaśnięcia dostępu

core.SyncOUInstances — jednostki organizacyjne

  • Id — unikalny identyfikator rekordu (auto-increment)
  • OrgUnitId (nvarchar, UNIQUE) — identyfikator OU z systemu źródłowego (kod OU, GUID itp.)
  • ParentId — FK do OrgUnitId (OU nadrzędna dla hierarchii)
  • Code — kod organizacyjny OU (np. “IT”, “HR”, “SALES”)
  • Name — nazwa jednostki organizacyjnej
  • IsActive (bit) — czy OU jest aktywna
  • ActiveFrom (datetime2) — data aktywacji
  • ActiveUntil (datetime2) — data deaktywacji (NULL jeśli bez ograniczenia)

core.SyncOUInstanceUsers — przypisania użytkowników do OU

  • OrgUnitId (nvarchar, FK) — referencja do SyncOUInstances.OrgUnitId
  • UserId (nvarchar, FK) — referencja do SyncUserProfiles.UserId
  • Tabela asocjacyjna bez własnego ID — określa powiązania użytkowników z jednostkami

core.SqlTableStatuses — statusy synchronizacji

  • Id — unikalny identyfikator
  • Name (nvarchar) — nazwa tabeli (SyncUserProfiles lub SyncOUInstances)
  • Status (int) — kod statusu (0=ReadyForData, 1=DataInput, 2=ReadyForSync, 3=InSync, 4=Error.)

Statusy synchronizacji są przechowywane w core.SqlTableStatuses na poziomie tabeli, nie na poziomie poszczególnych rekordów. Stan wskazuje na postęp całej partii danych dla danej tabeli. Tabela SyncOUInstanceUsers nie ma własnego statusu w SqlTableStatuses — jej synchronizacja jest zintegrowana z przetwarzaniem SyncOUInstances. Przypisania użytkowników do OU (zawarte w SyncOUInstanceUsers) są automatycznie przetwarzane w ramach synchronizacji jednostek organizacyjnych, bez osobnej kontroli statusu. Oznacza to, że:

  • Gdy załadujesz dane do SyncOUInstanceUsers, nie zmienią się statusy w SqlTableStatuses
  • Synchronizacja przypisań następuje automatycznie gdy SyncOUInstances ma status InSync
  • Ewentualne błędy w przypisaniach będą zaraportowane w logach TaskService podczas przetwarzania SyncOUInstances

Przygotowanie do pierwszej synchronizacji

Przed załadowaniem danych do tabel synchronizacyjnych:

  1. Przygotuj dane w systemie źródłowym i wyeksportuj je w wybranym formacie
  2. Zweryfikuj dane przed załadowaniem:
    • Czy identyfikatory użytkowników (UserId) są unikalne
    • Czy identyfikatory OU (OrgUnitId) są unikalne
    • Czy hierarchia OU jest spójna (wszystkie ParentId wskazują na istniejące OrgUnitId)
    • Czy przypisania użytkowników do OU są prawidłowe (SyncOUInstanceUsers zawiera tylko istniejące UserId i OrgUnitId)
  3. Załaduj dane do tabel synchronizacyjnych
    • SyncUserProfiles — profili użytkowników
    • SyncOUInstances — jednostek organizacyjnych
    • SyncOUInstanceUsers — przypisań użytkowników do OU
  4. Upewnij się, że status = ReadyForSync — jeśli załadujesz przez API, status ustawia się automatycznie; jeśli bezpośrednio SQL, musisz ustawić ręcznie
  5. Synchronizacja uruchomi się automatycznie — TaskService ma wbudowany timer, który zgodnie z konfiguracją tenanta co RepeatInterval sekund wyzwala synchronizację (patrz sekcja Jak działa synchronizacja)

Przebieg synchronizacji

Fazy synchronizacji

1. Import danych

Administrator lub skrypt ETL przygotowuje dane w tabelach przejściowych. Dane mogą być załadowane poprzez:

  • Procedury SQL (INSERT INTO SyncUserProfiles ...)
  • Skrypty ETL
  • Public API nAxiom (które obsługuje walidację i zmianę statusu)

Tabele są zasilane danymi z systemu źródłowego:

  • SyncUserProfiles — lista użytkowników
  • SyncOUInstances — struktura organizacyjna
  • SyncOUInstanceUsers — przypisania użytkowników do OU

Endpointy PublicAPI do zasilania tabel przejściowych

Jeśli dane są ładowane przez PublicAPI (zamiast bezpośrednio SQL), można użyć endpointów kontrolera StructureSynchronization.

Ogólny wzorzec ścieżki w PublicAPI to:

  • /{Controller}/{Action}

W praktyce dla synchronizacji struktury używane są:

  • POST /StructureSynchronization/UserProfileList
    • Zasila tabelę core.SyncUserProfiles
    • Body: obiekt z listą UserProfiles (dla każdego elementu m.in. UserId, ParentId, UserName, Email, FirstName, LastName, IsActive, ExpireDate)
  • POST /StructureSynchronization/OUInstanceList
    • Zasila tabelę core.SyncOUInstances
    • Body: obiekt z listą OUInstances (dla każdego elementu m.in. OrgUnitId, ParentId, Code, Name, IsActive, ActiveFrom, ActiveUntil)
  • POST /StructureSynchronization/OUInstanceUsersList
    • Zasila tabelę core.SyncOUInstanceUsers
    • Body: obiekt z listą OUInstanceUsers (dla każdego elementu: OrgUnitId, UserId)

Endpointy PublicAPI do importu danych wymagają poprawnej autoryzacji PublicAPI i odpowiednich uprawnień użytkownika technicznego. Przy imporcie przez API status tabel (core.SqlTableStatuses) jest obsługiwany automatycznie przez aplikację (w tym przejście do ReadyForSync).

Uwaga: endpoint POST /StructureSynchronization/SynchronizeStructure nie służy do zasilania tabel przejściowych. Służy do uruchomienia synchronizacji danych już załadowanych do tabel Sync*.

Przykładowe payloady JSON (PublicAPI)

Przykład dla POST /StructureSynchronization/UserProfileList:

{
  "userProfiles": [
    {
      "userProfile": {
        "id": 0,
        "userId": "u-001",
        "parentId": null,
        "userName": "jan.kowalski",
        "email": "jan.kowalski@acme.pl",
        "firstName": "Jan",
        "lastName": "Kowalski",
        "isActive": true,
        "expireDate": "2026-12-31T00:00:00"
      }
    }
  ]
}

Przykład dla POST /StructureSynchronization/OUInstanceList:

{
  "ouInstances": [
    {
      "ouInstance": {
        "id": 0,
        "orgUnitId": "OU-IT",
        "parentId": null,
        "code": "IT",
        "name": "Dzial IT",
        "isActive": true,
        "activeFrom": "2026-01-01T00:00:00",
        "activeUntil": null
      }
    }
  ]
}

Przykład dla POST /StructureSynchronization/OUInstanceUsersList:

{
  "ouInstanceUsers": [
    {
      "ouInstanceUser": {
        "orgUnitId": "OU-IT",
        "userId": "u-001"
      }
    }
  ]
}

Nazwy właściwości JSON podawaj zgodnie z kontraktem API (jak w przykładach powyżej). W praktyce integracyjnej najbezpieczniej najpierw wykonać test na pojedynczym rekordzie, a dopiero potem wysyłać pełne paczki danych.

2. Automatyczne wyzwolenie synchronizacji (nie ma ręcznego “uruchamiania”)

TaskService ma wbudowany timer (StructureSynchronizationConnector), który:

  • Co RepeatInterval sekund (z konfiguracji) sprawdza status tabel w SqlTableStatuses
  • Szuka tabel ze statusem ReadyForSync (kod 2)
  • Jeśli znaleziona, zmienia status na InSync (kod 3) i uruchamia synchronizację

Wymagane kroki:

  1. Załaduj dane do tabel przejściowych
  2. Upewnij się, że status w SqlTableStatuses dla obu tabel (SyncUserProfiles, SyncOUInstances) wynosi ReadyForSync (= 2)
  3. Czekaj na timer TaskService — synchronizacja uruchomi się automatycznie w następnym cyklu

Jeśli dane są załadowane przez Public API, zmiana statusu na ReadyForSync następuje automatycznie. Jeśli załadujesz dane bezpośrednio SQL, musisz ręcznie ustawić status:

UPDATE core.SqlTableStatuses SET Status = 2 WHERE Name = 'SyncUserProfiles'
UPDATE core.SqlTableStatuses SET Status = 2 WHERE Name = 'SyncOUInstances'

3. Przetwarzanie i aktualizacja struktury

TaskService:

  • Odczytuje dane z tabel przejściowych (SyncUserProfiles, SyncOUInstances, SyncOUInstanceUsers)
  • Przetwarza je zgodnie z wybranym trybem (Full, Update, Differential)
  • Aktualizuje strukturę w tabelach docelowych (UserProfiles, OUInstances, OUInstanceUsers)
  • Przypisania użytkowników z SyncOUInstanceUsers są przetwarzane automatycznie w ramach synchronizacji SyncOUInstances

4. Monitorowanie i weryfikacja

Administrator monitoruje statusy synchronizacji:

  • Statusy w SqlTableStatuses wskazują postęp (ReadyForDataDataInput [przy imporcie przez API] → ReadyForSyncInSyncReadyForData lub Error)
  • Błędy są zaraportowane w logach TaskService
  • W razie problemów dane w tabelach przejściowych pozostają dostępne do analizy

Schemat czasowy

Synchronizacja jest w pełni automatyczna:

  • TaskService ma timer, który co RepeatInterval sekund (typowo 60-300 sekund, zależy od konfiguracji tenanta) sprawdza status
  • Synchronizacja jest wyzwalana automatycznie gdy status = ReadyForSync
  • Administrator nie ma GUI ani polecenia do ręcznego uruchamiania — synchronizacja działa w tle
  • Jedynym sposobem kontroli jest:
    • Zmiana RepeatInterval w konfiguracji tenanta (aby zmieniła się częstotliwość polingu)
    • Ustawienie statusu na ReadyForSync (aby wyzwolić synchronizację w następnym cyklu timera)
    • Monitorowanie logów — aby zobaczyć czy synchronizacja się powiodła

Tryby synchronizacji

W konfiguracji tenanta ustawienie ‘SynchrozationType’ określa tryb synchronizacji czyli, jak dane z tabel przejściowych są stosowane do struktury docelowej. Do dyspozycji są trzy główne tryby:

Tryb Dodawanie nowych rekordów Aktualizacja istniejących Deaktywacja brakujących Typowe zastosowanie
Full Tak Tak Tak Pełne odświeżenie struktury na podstawie kompletnego źródła danych
Update Nie Tak Tak Aktualizacja rekordów już istniejących w nAxiom, bez zakładania nowych
Differential Tak Tak Tak Synchronizacja oparta o dane różnicowe; w praktyce bardzo zbliżona do trybu Full

Tryb Update nie tworzy nowych użytkowników ani nowych jednostek organizacyjnych. Jeżeli podczas synchronizacji system nie znajdzie odpowiednika danego rekordu w strukturze docelowej, rekord zostanie pominięty. Jednocześnie tryb ten nadal może deaktywować obiekty brakujące w danych źródłowych.

Tryb Full (Pełna synchronizacja)

Tryb ten implementuje najpełniejszą synchronizację danych:

  • Dodaje nowych użytkowników i OU
  • Aktualizuje istniejące rekordy (dane, status)
  • Deaktywuje użytkowników i OU brakujące w danych źródłowych (użytkownik istnieje w nAxiom, ale nie ma go w tabelach przejściowych)

Zastosowanie: Idealne do pełnego odświeżenia struktury, gdzie dane źródłowe zawsze odzwierciedlają aktualną rzeczywistość. Po synchronizacji struktura w nAxiom będzie dokładnym odzwierciedleniem danych źródłowych.

Uwaga: Deaktywowanie brakujących użytkowników może wpłynąć na dostęp i uprawnienia. Należy upewnić się, że dane źródłowe zawierają wszystkich użytkowników, którzy powinni być aktywni.

Tryb Update (Aktualizacja)

Tryb ten jest bardziej konserwatywny:

  • Aktualizuje istniejące użytkowników i OU (dane i status)
  • Nie dodaje nowych rekordów
  • Deaktywuje użytkowników i OU brakujące (tak jak w trybie Full)

Zastosowanie: Gdy struktura bazowa istnieje już w nAxiom, a chcemy aktualizować tylko dane istniejących rekordów. Zapobiega przypadkowemu dodaniu duplikatów, ale nadal stosuje deaktywowanie brakujących rekordów.

Uwaga: Semantycznie tryb “Update” zawiera również akcję deaktywowania, co może być nieintuicyjne. Umownie, deaktywowanie brakujących jest powszechnym zachowaniem synchronizacji.

Tryb Differential (Synchronizacja różnicowa)

Praktycznie zachowuje się podobnie do trybu Full, ale logika wewnętrzna jest zoptymalizowana do wskaźników różnic między danymi:

  • Dodaje nowe rekordy
  • Aktualizuje istniejące
  • Deaktywuje brakujące

Zastosowanie: Gdy chcemy zachować logikę Full, ale dane źródłowe są dostępne jako zbiory delta (wpisy nowe, zmienione, usunięte) zamiast całej listy.

Wybór trybu

Decyzja o wyborze trybu zależy od:

  • Dostępności kompletnych danych — jeśli dane źródłowe zawsze zawierają pełną listę, stosuj tryb Full
  • Bezpieczeństwa — jeśli chcesz uniknąć przypadkowej deaktywacji, rozważ ograniczenia na poziomie bazy danych
  • Nowych vs. istniejących danych — tryb Update jest bezpieczniejszy dla struktur, które już zawierają dane lokalne

Jak działa synchronizacja — techniczny przebieg

Timer TaskService (StructureSynchronizationConnector)

TaskService zawiera wbudowany usługę SynchronizeStructureTimedHostedService, która:

Inicjowanie:

  • Startuje automatycznie gdy tenant jest aktywowany
  • Konfiguracja pobierana z StructureSynchronizationConfiguration.RepeatInterval (czas w sekundach)

Cykliczny monitoring:

  • Co RepeatInterval sekund timer sprawdza tabelę core.SqlTableStatuses
  • Szuka wpisów dla SyncUserProfiles i SyncOUInstances
  • Sprawdza czy Status = 2 (ReadyForSync)

Wyzwolenie synchronizacji:

Jeśli Status == ReadyForSync (2):
  1. Zmiana Status → InSync (3)
  2. Uruchomienie SynchronizeStructureFromSyncTableHandler
  3. Odczyt danych z tabel przejściowych
  4. Przetworzenie zgodnie z trybem
  5. Aktualizacja tabel docelowych
  6. Zmiana Status → ReadyForData (0) [sukces] lub Error (4) [błąd]

Parametry:

  • RepeatInterval: domyślnie 60-300 sekund (zależy od instalacji)
  • Parametry pochodzą z konfiguracji tenanta, w szczególności z sekcji StructureSynchronizationConfiguration; wartość 0 wyłącza synchronizację
  • UWAGA: RepeatInterval nie jest ustawieniem tabel synchronizacyjnych ani bazy danych. Jest elementem konfiguracji tenanta odczytywanej przez TaskService.

Ustawienie statusu ReadyForSync

Status ReadyForSync (kod 2) powinien być ustawiony na dwa sposoby:

1. API (zalecane):

  • Załadowanie danych przez API automatycznie ustawia Status = ReadyForSync po wkładzie danych
  • Przykład: SaveSyncTableUserProfileListHandler po INSERT danych zmienia status na 2

2. Ręcznie SQL (dla zaawansowanych):

  • Jeśli załadujesz dane bezpośrednio INSERT, musisz ręcznie ustawić status:
    UPDATE core.SqlTableStatuses SET Status = 2 WHERE Name = 'SyncUserProfiles'
    UPDATE core.SqlTableStatuses SET Status = 2 WHERE Name = 'SyncOUInstances'
    
  • Po tym kroku timer TaskService w następnym cyklu wyzwoli synchronizację

Statusy i monitorowanie

Cykl statusów synchronizacji

Statusy synchronizacji są przechowywane w tabeli core.SqlTableStatuses na poziomie całej tabeli (nie na poziomie poszczególnych rekordów). Dla tabel przejściowych SyncUserProfiles i SyncOUInstances istnieje rekord w SqlTableStatuses z jego aktualnym stanem:

Status Znaczenie Opis
0 — ReadyForData Gotów do przyjęcia danych Tabela oczekuje na załadowanie danych z systemu źródłowego
1 — DataInput Dane są ładowane Trwa wczytywanie danych do tabeli
2 — ReadyForSync Gotów do synchronizacji Dane są kompletne i gotowe do przetworzenia
3 — InSync Synchronizacja w trakcie Trwa przetwarzanie danych i aktualizacja tabel systemowych
4 — Error Błąd Podczas synchronizacji wystąpił błąd; szczegóły są dostępne w logach TaskService

Uwaga: Tabela SyncOUInstanceUsers nie ma własnego statusu w SqlTableStatuses. Jej synchronizacja jest automatyczną częścią przetwarzania SyncOUInstances. To oznacza:

  • Przypisania użytkowników do OU są przetwarzane razem z OU na podstawie statusu SyncOUInstances
  • Gdy SyncOUInstances ma status InSync (3), również dane z SyncOUInstanceUsers są synchronizowane w tym samym cyklu
  • Brakuje osobnej kontroli statusu dla przypisań — są one zawsze przetwarzane razem z jednostkami

Monitorowanie synchronizacji

Aby monitorować przebieg synchronizacji:

  1. Sprawdź statusy tabeliSELECT * FROM core.SqlTableStatuses WHERE Name IN ('SyncUserProfiles', 'SyncOUInstances')
    • Uwaga: Brak statusu dla SyncOUInstanceUsers — jest ona przetwarzana razem z SyncOUInstances
  2. Obserwuj zawartość tabel — czy rekordy w SyncUserProfiles, SyncOUInstances i SyncOUInstanceUsers zawierają oczekiwane dane
  3. Przeanalizuj błędy — jeśli status to 4 (Error), przejrzyj logi TaskService w celu znalezienia szczegółów
  4. Porównaj dane — porównaj zawartość tabel przejściowych z tabelami docelowymi (UserProfiles, OUInstances)

Logi synchronizacji

TaskService loguje każde uruchomienie synchronizacji, w tym:

  • Datę i godzinę
  • Tryb synchronizacji
  • Liczbę przetworzonych rekordów
  • Błędy i ostrzeżenia
  • Czas trwania

Logi pomagają w diagnostyce problemów i analizie historii synchronizacji.

Status nie zawsze odzwierciedla rzeczywisty stan synchronizacji

TaskService uruchamia cykl synchronizacji co RepeatInterval i po zakończeniu cyklu może ustawić status na ReadyForData (0), nawet jeśli w poprzednim cyklu wystąpił Error (4). W praktyce można zaobserwować sekwencję: 2 (ReadyForSync) -> 3 (InSync) -> 4 (Error) -> po kolejnym odświeżeniu/cyklu 0 (ReadyForData).

Oznacza to, że status=ReadyForData nie gwarantuje, że poprzednia próba synchronizacji przebiegła bez błędów. Status informuje o bieżącej gotowości tabeli do przyjęcia kolejnych danych, a nie o jakości poprzedniego przebiegu.

Administrator MUSI regularnie sprawdzać logi TaskService, aby upewnić się, że synchronizacja faktycznie się powiodła. Błędy (np. duplikaty, naruszenia FK, konflikty danych) mogą być zaraportowane tylko w logach, a status będzie wyglądać na “OK”.

Praktyka: Po każdej synchronizacji:

  1. Sprawdź status w SqlTableStatuses — czy zmienił się na 0 (ReadyForData)
  2. Przejrzyj logi TaskService z ostatnich minut — szukaj błędów, ostrzeżeń, liczby przetworzonych rekordów
  3. Opcjonalnie: Porównaj liczbę rekordów w tabelach przejściowych z liczbą zsynchronizowanych rekordów (może się nie zgadzać jeśli były błędy)

Rozwiązywanie problemów

Synchronizacja nie zaczyna się

Przyczyny:

  • Timer TaskService nie jest uruchomiony (serwis nie działa itp.)
  • Tabele przejściowe są puste (brak danych w SyncUserProfiles lub SyncOUInstances)
  • Status w SqlTableStatuses nie jest ReadyForSync (2) — synchronizacja czeka tylko na ten status
  • RepeatInterval jest bardzo duży — timer sprawdza rzadko, czekaj dłużej

Rozwiązanie:

  • Sprawdź, czy TaskService jest uruchomiony (pula aplikacji lub kontener)
  • Weryfikuj, czy dane zostały załadowane do tabel przejściowych:
    SELECT COUNT(*) FROM core.SyncUserProfiles; 
    SELECT COUNT(*) FROM core.SyncOUInstances;
    
  • Sprawdź statusy i RepeatInterval:
    SELECT * FROM core.SqlTableStatuses WHERE Name IN ('SyncUserProfiles', 'SyncOUInstances');
    
    • Sprawdź RepeatInterval w konfiguracji tenanta, w sekcji StructureSynchronizationConfiguration. Jeśli RepeatInterval jest równe 0 lub brak tego ustawienia, timer się nie uruchamia lub sprawdza status zbyt rzadko.
  • Jeśli status to 0 (ReadyForData) a chcesz wyzwolić synchronizację, ustaw go na 2:
    UPDATE core.SqlTableStatuses SET Status = 2 WHERE Name IN ('SyncUserProfiles', 'SyncOUInstances')
    
  • Czekaj RepeatInterval sekund na uruchomienie timera (np. jeśli RepeatInterval=60, czekaj minutę)

Użytkownicy lub OU nie są synchronizowani

Przyczyny:

  • Brakujące dane w tabelach przejściowych
  • Hierarchia OU jest uszkodzona (OU nadrzędna nie istnieje)
  • Przypisania użytkowników (SyncOUInstanceUsers) są niekompletne
  • Identyfikatory użytkowników nie zgadzają się między tabelami

Rozwiązanie:

  • Sprawdź dane w SyncUserProfiles i SyncOUInstances — czy wszystkie wymagane pola są wypełnione
  • Zweryfikuj hierarchię OU — wszystkie OU nadrzędne muszą być zdefiniowane
  • Sprawdź przypisania w SyncOUInstanceUsers — czy użytkownicy są przypisani do OU
  • Porównaj wartości identyfikatorów między tabelami

Błędy synchronizacji — status Error

Przyczyny:

  • Naruszenie integralności danych (duplikaty UserId lub OrgUnitId, wartości NULL w wymaganych polach)
  • Uszkodzona hierarchia (ParentId wskazuje na nieistniejący rekord)
  • Konflikt z istniejącymi danymi w tabelach docelowych
  • Problem z uprawnieniami bazy danych dla TaskService

Rozwiązanie:

  • Odczytaj komunikat błędu z logów TaskService
  • Wyczyść dane tabel przejściowych i spróbuj ponownie załadować dane (bezpiecznie dla relacji FK): DELETE FROM core.SyncOUInstanceUsers; DELETE FROM core.SyncUserProfiles; DELETE FROM core.SyncOUInstances;
  • Zweryfikuj integrację danych przed załadowaniem:
    • Czy UserId są unikalne w SyncUserProfiles?
    • Czy OrgUnitId są unikalne w SyncOUInstances?
    • Czy wszystkie ParentId w SyncOUInstances wskazują na istniejące OrgUnitId?
    • Czy wszyscy użytkownicy w SyncOUInstanceUsers istnieją w SyncUserProfiles?
  • Jeśli problem utrzymuje się, zweryfikuj konta bazy danych — czy TaskService ma uprawnienia do odczytu i zapisu

Deaktywowani użytkownicy utracili dostęp

Przyczyna:

  • Uruchomiono synchronizację w trybie Full lub Update, a użytkowników nie ma w danych źródłowych

Rozwiązanie:

  • Sprawdź, czy użytkownicy faktycznie powinni być deaktywowani
  • Jeśli deaktywacja była błędem, przywróć dane z kopii zapasowej
  • Zmień tryb synchronizacji na bardziej konserwatywny (np. Update zamiast Full)
  • Jeśli to możliwe, skonfiguruj filtrowanie na poziomie TaskService, aby nie deaktywować wybranych użytkowników

Przypisania użytkowników do OU nie są synchronizowane

Przyczyny:

  • Dane w SyncOUInstanceUsers są załadowane, ale status SyncOUInstances jest 0 (ReadyForData) — synchronizacja nie została uruchomiona
  • Uszkodzone referencje FK — UserId lub OrgUnitId w SyncOUInstanceUsers wskazują na nieistniejące rekordy
  • Luka w danych — niektórych użytkowników lub OU nie ma w SyncUserProfiles lub SyncOUInstances

Rozwiązanie:

  • Upewnij się, że status SyncOUInstances to 2 (ReadyForSync) — przypisania są przetwarzane razem z OU
  • Sprawdź integrość danych (patrz skrypt walidacji FK w sekcji Przydatne skrypty SQL)
  • Jeśli wszystkie dane są prawidłowe, ale przypisania nie zostały zsynchronizowane, poczekaj aż synchronizacja przejdzie do statusu 3 (InSync)
  • Sprawdź logi TaskService

Przyczyna (w wersji wcześniejszej):

  • W starszych wersjach nAxiom przed wersją 1.15.6.4 synchronizacja agresywnie czyszczała przypisania użytkowników do OU

Rozwiązanie:

  • Upewnij się, że korzystasz z wersji 1.15.6.4 lub nowszej, która zawiera poprawkę
  • Przy aktualizacji z wersji starszej przywróć przypisania z kopii zapasowej lub przesynchronizuj dane

Synchronizacja wygląda na udaną, ale dane nie są aktualizowane

Przyczyna:

  • Status zmienił się na ReadyForData (0), ale w logach TaskService są błędy
  • Część danych została zsynchronizowana, część odrzucona z powodu błędów
  • Status nie wskazuje na błędy — zmienia się na ReadyForData niezależnie od powodzenia

Rozwiązanie:

  • Zawsze sprawdzaj logi TaskService — status ReadyForData nie gwarantuje powodzenia
  • Przejrzyj logi z czasu synchronizacji — szukaj:
    • Błędów: “Error”, “Exception”, “Failed”
    • Ostrzeżeń: “Warning”, “skipped”, “ignored”
    • Liczby przetworzonych vs. załadowanych rekordów — czy się zgadzają?
  • Porównaj dane w tabelach docelowych (UserProfiles, OUInstances) z liczbą w tabelach przejściowych — jeśli liczby się nie zgadzają, część danych została odrzucona
  • Sprawdź szczegóły błędów w logach — mogą wskazywać na:
    • Duplikaty klucza w danych źródłowych
    • Naruszenia integralności danych (NULL w wymaganych polach)
    • Konflikty z istniejącymi danymi

Praktyka bezpieczna:

  1. Po każdej synchronizacji odczekaj kilka minut
  2. Sprawdzaj status — czy zmienił się na 0 (ReadyForData)
  3. Przejrzyj logi TaskService z ostatniego okresu (co najmniej 10 minut wstecz)
  4. Sprawdź liczbę rekordów:
    -- Liczba w tabelach przejściowych
    SELECT COUNT(*) FROM core.SyncUserProfiles;
    SELECT COUNT(*) FROM core.SyncOUInstances;
       
    -- Liczba w tabelach docelowych
    SELECT COUNT(*) FROM core.UserProfiles;
    SELECT COUNT(*) FROM core.OUInstances;
    
  5. Jeśli liczby się nie zgadzają lub są błędy w logach — przeprowadź diagnostykę

Timer TaskService nie wyzwala synchronizacji mimo ustawienia ReadyForSync

Przyczyny:

  • Timer nie jest uruchomiony (serwis nie startuje, zawiesił się)
  • Konfiguracja RepeatInterval jest ustawiona na 0 lub bardzo dużą wartość
  • Serwis TaskService ma błędy w logach, które uniemożliwiają działanie timera

Rozwiązanie:

  • Sprawdź, czy TaskService jest aktywny — czy serwis uruchamia się, czy ma statusu “running”
  • Przeczytaj logi TaskService z ostatnich minut — szukaj błędów wokół “StructureSynchronizationConnector”, “SynchronizeStructure”
  • Sprawdź konfigurację RepeatInterval w konfiguracji tenanta, w sekcji StructureSynchronizationConfiguration. Jeśli RepeatInterval wynosi 0 lub brak tego ustawienia, timer się nie uruchamia. Zmień wartość na rozsądną (60-300 sekund) i zrestartuj TaskService.
  • Jeśli timer startuje ale nie reaguje, spróbuj zrestartować serwis TaskService
  • Jeśli problem utrzymuje się, sprawdź czy nie ma deadlocka w bazie — czy inne procesy blokują SqlTableStatuses

Przydatne skrypty SQL

Sprawdzenie statusów synchronizacji

-- Pokaż aktualny status każdej tabeli synchronizacyjnej
SELECT Name, Status, 
  CASE Status
    WHEN 0 THEN 'ReadyForData'
    WHEN 1 THEN 'DataInput'
    WHEN 2 THEN 'ReadyForSync'
    WHEN 3 THEN 'InSync'
    WHEN 4 THEN 'Error'
    ELSE 'Unknown'
  END AS StatusName
FROM core.SqlTableStatuses
WHERE Name IN ('SyncUserProfiles', 'SyncOUInstances')
ORDER BY Name;

Liczba załadowanych danych

-- Liczba rekordów w tabelach synchronizacyjnych
SELECT 
  'SyncUserProfiles' AS TableName, COUNT(*) AS RecordCount FROM core.SyncUserProfiles
UNION ALL
SELECT 'SyncOUInstances', COUNT(*) FROM core.SyncOUInstances
UNION ALL
SELECT 'SyncOUInstanceUsers', COUNT(*) FROM core.SyncOUInstanceUsers;

Walidacja integracji danych

-- Sprawdzenie duplikatów UserId
SELECT UserId, COUNT(*) AS DupCount
FROM core.SyncUserProfiles
GROUP BY UserId
HAVING COUNT(*) > 1;

-- Sprawdzenie duplikatów OrgUnitId
SELECT OrgUnitId, COUNT(*) AS DupCount
FROM core.SyncOUInstances
GROUP BY OrgUnitId
HAVING COUNT(*) > 1;

-- Sprawdzenie, czy ParentId w OU wskazują na istniejące OrgUnitId
SELECT DISTINCT ParentId
FROM core.SyncOUInstances
WHERE ParentId IS NOT NULL
  AND ParentId NOT IN (SELECT OrgUnitId FROM core.SyncOUInstances);

-- Sprawdzenie, czy wszyscy użytkownicy w przypisaniach istnieją
SELECT DISTINCT u.UserId
FROM core.SyncOUInstanceUsers u
WHERE u.UserId NOT IN (SELECT UserId FROM core.SyncUserProfiles);

-- Sprawdzenie, czy wszystkie OU w przypisaniach istnieją
SELECT DISTINCT o.OrgUnitId
FROM core.SyncOUInstanceUsers o
WHERE o.OrgUnitId NOT IN (SELECT OrgUnitId FROM core.SyncOUInstances);

Resetowanie statusu synchronizacji

-- Ustaw status na ReadyForSync (2) aby wyzwolić synchronizację w następnym cyklu timera
UPDATE core.SqlTableStatuses SET Status = 2 WHERE Name = 'SyncUserProfiles'
UPDATE core.SqlTableStatuses SET Status = 2 WHERE Name = 'SyncOUInstances'

Monitoring timera TaskService i konfiguracji

Aby sprawdzić RepeatInterval w konfiguracji tenanta:

  • Szukaj sekcji StructureSynchronizationConfiguration
  • Parametr: RepeatInterval
  • Wartość w sekundach — jak często timer sprawdza SqlTableStatuses
  • Po zmianie RepeatInterval: zrestartuj TaskService

Wyzwolenie synchronizacji (manual trigger)


-- 1. Załaduj dane (przykład)
DELETE FROM [core].[SyncOUInstanceUsers];
DELETE FROM [core].[SyncUserProfiles];
DELETE FROM [core].[SyncOUInstances];

INSERT INTO [core].[SyncUserProfiles] (UserId, UserName, FirstName, LastName, Email, IsActive, ExpireDate)
VALUES ('user001', 'john.doe', 'John', 'Doe', 'john@company.com', 1, '2026-12-31');

INSERT INTO [core].[SyncOUInstances] (OrgUnitId, Code, Name, IsActive, ActiveFrom, ActiveUntil, ParentId)
VALUES ('IT001', 'IT', 'Information Technology', 1, '2026-01-01', NULL, NULL);

-- 2. Ustaw status na ReadyForSync (2)
UPDATE [core].[SqlTableStatuses] SET Status = 2 WHERE Name = 'SyncUserProfiles';
UPDATE [core].[SqlTableStatuses] SET Status = 2 WHERE Name = 'SyncOUInstances';

-- 3. Czekaj RepeatInterval sekund — timer TaskService wyzwoli synchronizację
-- 4. Sprawdzaj status:
SELECT Name, Status, 
  CASE Status
    WHEN 0 THEN 'ReadyForData (gotowe)'
    WHEN 1 THEN 'DataInput (ładowanie)'
    WHEN 2 THEN 'ReadyForSync (czeka na timer)'
    WHEN 3 THEN 'InSync (synchronizacja w trakcie)'
    WHEN 4 THEN 'Error (błąd)'
  END AS StatusText
FROM [core].[SqlTableStatuses]
WHERE Name IN ('SyncUserProfiles', 'SyncOUInstances');

Czyszczenie tabel (UWAGA: nieodwracalne!)

-- Usuń wszystkie dane z tabel synchronizacyjnych
-- UWAGA: Najpierw wykonaj kopię zapasową!
DELETE FROM core.SyncOUInstanceUsers;
DELETE FROM core.SyncUserProfiles;
DELETE FROM core.SyncOUInstances;

Bezpieczne praktyki

  • Zawsze wykonaj kopię zapasową przed uruchomieniem synchronizacji w trybie Full
  • Testuj na środowisku testowym przed wdrożeniem na produkcji
  • Monitoruj logi TaskService — status ReadyForData nie gwarantuje powodzenia synchronizacji; zawsze sprawdzaj logi pod kątem błędów
  • Sprawdzaj liczę rekordów po synchronizacji — porównaj dane w tabelach przejściowych z tabelami docelowymi
  • Dokumentuj zmiany — kiedy przeprowadzono synchronizację, w jakim trybie, jakie były wyniki (szczególnie czy były błędy w logach)
  • Waliduj dane źródłowe przed załadowaniem do tabel przejściowych — brakujące lub nieprawidłowe dane mogą prowadzić do niespójności struktury
  • Regularne przeglądy logów — ustaw proces monitorowania logów TaskService (np. codzienne przeglądy, alerting na błędy)
|← Logowanie za pomocą hasła |↑ Do góry |→ Model uprawnień PBA |

Copyright © 2025 OPTEAM SA. Theme Copyright © 2017-2020 Patrick Marsceill. Distributed by an MIT license.