| Auszug | ||
|---|---|---|
| ||
Nuclos Mandanten Migration: zwei Systeme zusammenführen, Management Console, -uniqueMandator, pg_dump, on-conflict-do-nothing, Foreign Keys, Zusammenführung. |
Sprache: Deutsch · English
Zwei Nuclos-Systeme desselben Nuclets zu einem Mandanten-System zusammenführen – Schritt für Schritt mit SQL und pg_dump.
| Status | ||||
|---|---|---|---|---|
|
| Status | ||||
|---|---|---|---|---|
|
| Status | ||||
|---|---|---|---|---|
|
| Status | ||||
|---|---|---|---|---|
|
| Panel | ||||||
|---|---|---|---|---|---|---|
| ||||||
Auf dieser Seite
|
...
| Warnung | ||
|---|---|---|
| ||
Erstelle vor jedem Schritt ein Backup der Datenbank. Lies zuvor die Seite Mandant. Beispiele beziehen sich auf PostgreSQL; für andere Datenbanken sind Anpassungen nötig. |
Dieses How-to führt
...
zwei Systeme, die auf
...
demselben Nuclet basieren, zu einem
...
System mit zwei Mandanten
...
Um ein alleinstehendes System, das zukünftig von mehreren Mandanten genutzt werden soll mandantenfähig zu machen, kann wie hier unter Punkt 2, 3 und 7 beschrieben vorgegangen werden. Unbedingt sollte vorher der Artikel Mandant gelesen werden.
Es sollte außerdem überlegt werden ob das hier beschrieben Vorgehen für den konkreten Fall sinnvoll ist - abhängig von der Komplexität des Datenmodells, der Menge der Daten und den funktionalen Anforderungen an die Mandantenfähigkeit.
Die verwendete Datenbank ist PostgreSQL, ein ähnliches Vorgehen sollte aber auch für andere Datenbanken funktionieren
| Warnung |
|---|
Vor der Verwendung diese How-Tos oder der Einrichtung der mandantenfähigkeit generell sollte auf jeden Fall ein Backup der Datenbank erstellt werden, falls es während dessen zu Fehlern oder Problemen kommt. |
| Tipp |
|---|
Ggf. müssen noch Anpassungen für eine gemeinsam verwendete Nucletversion gemacht werden. Dabei können Unterschiede in der Funktionalität oft über Nucletparameter oder über separate Benutzergruppen, denen dann z.B. unterschiedliche Druckausgaben zugeordnet werden können, abgebildet werden. |
Zuerst wird unter dem Menüpunkt Administration → Mandant auf beiden Systemen jeweils ein Mandant (und damit die zugehörige Mandantenebene) angelegt.
zusammen. Die Daten jedes Systems werden je einem Mandanten zugeordnet; zunächst werden keine Daten geteilt. Ein einzelnes System machst du über die Punkte 2, 3 und 7 mandantenfähig.
Auf beiden Systemen unter Administration → Mandant je einen Mandanten anlegen, dann die UID der Mandantenebene per SQL angleichen
...
:
| Codeblock | ||
|---|---|---|
| ||
INSERT INTO t_md_mandator_level(
struid, strname, intversion, blnshowname, datcreated, strcreated, datchanged, strchanged
) VALUES(
'tmp', 'tmp', 1, false, current_date, 'me', current_date, 'me'
);
UPDATE t_md_mandator SET struid_t_md_mandator_level = 'tmp';
UPDATE t_md_mandator_level SET struid = '<struid auf anderem System>' WHERE struid <> 'tmp';
UPDATE t_md_mandator SET struid_t_md_mandator_level = '<struid auf anderem System>';
DELETE FROM t_md_mandator_level WHERE struid = 'tmp'; |
Mandantenabhängige
...
Nucletparameter und Ressourcen
...
Insofern nicht auf beiden Systemen (und von beiden zukünftigen Mandanten) stets der gleiche Wert verwendet werden soll, müssen Nucletparameter auf Mandantenabhängige Werte gesetzt werden. Dies erfolgt ebenfalls unter dem Menüpunkt Administration → Mandant im entsprechenden Reiter. Die restlichen Nucletparameter sowie alle Systemparameter müssen auf beiden Systemen auf denselben Wert gesetzt werden.
Das gleiche Vorgehen wird für Ressourcen, wie z.B. Bilddateien für Logos u.ä. wiederholt.
Benutzeraccounts vorbereiten
(Logos o.ä.) setzen; alle übrigen Parameter auf beiden Systemen gleich halten.
Es darf keine identischen Benutzernamen geben – auf einem System umbenennen und alle Benutzer dem jeweiligen Mandanten zuordnen (Sammelbearbeitung)
...
:
| Codeblock | ||
|---|---|---|
| ||
UPDATE t_md_user set struser = struser || '-<Mandant>'; |
...
Anschließend sollten auf beiden System alle User dem jeweiligen Mandanten zugeordnet werden (Mit Hilfe der Sammelbearbeitung möglich).
Konsistenz der Datenbanken prüfen
...
Pro Businessobjekt über die Management Console aktivieren und den initialen
...
Mandanten setzen
...
Im nächsten Schritt wird für die gewünschten Businessobjekte (in unserem Szenario zunächst alle) die Mandantenfähigkeit (also die Trennung der Datenbestände) aktiviert und der initiale Mandant gesetzt.
Dies ist mithilfe des folgenden Befehls auf der Managementkonsole möglich:
:
| Codeblock | ||
|---|---|---|
|
...
-package <nuclet-package> -bo “<BO-Name>” -level 1 -initial <Mandantenname> [-uniqueMandator] |
...
Das Flag -uniqueMandator
...
macht den Mandanten Teil des
...
Enthält eines der Argumente Leerzeichen, so ist es in Anführungszeichen zu setzen.
...
Unique-Keys. Für viele BOs erzeugt folgendes SQL ein Migrationsskript:
| Codeblock | ||
|---|---|---|
|
...
set search_path to <schema_name>;
SELECT (
'UPDATE t_md_entity SET ' || E'\n' ||
'blnmandatorunique = true, ' || E'\n' ||
'struid_t_md_mandator_level= ' ||
'''' || (SELECT struid FROM t_md_mandator_level LIMIT 1) || '''' || ';' || E'\n' ||
'-- Lege Spalte für Mandator in BO-Tabellen an' || E'\n' ||
(SELECT
STRING_AGG(
'ALTER TABLE ' || strdbentity || ' ADD COLUMN IF NOT EXISTS struid_nuclosmandator character varying(128); ' || E'\n' ||
'UPDATE ' || strdbentity || ' SET struid_nuclosmandator = ' || '''' || (SELECT struid FROM t_md_mandator LIMIT 1) || '''' || ';' || E'\n' ||
'ALTER TABLE ' || strdbentity || ' ALTER COLUMN struid_nuclosmandator SET NOT NULL',
';' || E'\n'
)
FROM t_md_entity
WHERE strvirtualentity IS NULL
) || ';' || E'\n'
) |
Per shell-Befehl kann migrate_entities.sql ausgeführt, das erzeugte Skript in einer weiteren Datei zwischengespeichert und anschließend ebenfalls ausgeführt werden:
| Codeblock | ||
|---|---|---|
| ||
psql [-U "<connect with db user>"]-qAtX <DB-name> < migrate_entities.sql > do_migrate_entities.sql
psql [-U "<connect with db user>"] <DB-name> < do_migrate_entities.sql |
Das Skript setzt für alle BOs des Systems das Mandantenlevel und den Mandator sowie die boolean-Spalte blnmandatorunique auf true (entspricht dem flag -uniqueMandator).
...
Soll nach Ausführung des Skripts noch weitere Anpassungen an einem der Systeme vorgenommen werden müssen zunächst folgende Befehle auf der Managementkonsole ausgeführt werden, damit die Änderungen übernommen werden:
...
invalidate caches
...
rebuild classes
| Info | ||
|---|---|---|
| ||
Nach nachträglichen Änderungen auf der Management Console ausführen: |
|
...
...
Verwaiste Dokumentreferenzen zuerst entfernen:
| Codeblock | ||
|---|---|---|
| ||
DELETE FROM <schema_name>.t_md_importfile WHERE struid_documentfile = 'null';
DELETE FROM <schema_name>.t_ud_go_document WHERE struid_t_ud_documentfile = 'null';
DELETE FROM <schema_name>.t_ud_documentfile WHERE struid = 'null'; |
...
...
...
Großteil der
...
Daten
...
als COPY-Statements
...
exportieren (<nuclet_prefix> = lokaler Nuclet-Identifizierer):
| Codeblock | ||
|---|---|---|
| ||
pg_dump --file "my_exported_data.sql" --host "<db host>" --port "<db port>" [--username "<connect with db user>"] [--no-password] --verbose --format=p --blobs --data-only --no-owner --no-privileges --no-tablespaces --no-unlogged-table-data --no-comments --schema "<schema_name>" -t "^<schema_name>.<nuclet_prefix>*" -t <schema_name>.t_md_mandator -t <schema_name>.t_md_mandator_accessible -t <schema_name>.t_md_user -t <schema_name>.t_md_role_user -t <schema_name>.t_md_mandator_param_value -t <schema_name>.t_md_mandator_role_user -t <schema_name>.t_md_passwordhistory -t <schema_name>.t_md_user_setting -t <schema_name>.t_ud_searchfilter_user -t <schema_name>.t_ud_genericobject -t "<schema_name>.t_ud_document*" -t "<schema_name>.t_ud_go_*" -t <schema_name>.t_ud_history -t <schema_name>.t_ud_lock -t <schema_name>.t_ud_entityobject_relation -t <schema_name>.t_ud_logbook -t <schema_name>.t_ud_timelimittask -t "<db name>" |
Mit <nuclet_prefix> ist der lokale Identifizierer des Nuclets gemeint, mit dem alle Tabellennamen beginnen, die Datensätze von Businessobjekten beinhalten. Neben den Tabellen für die Businessobjekte werden Metadaten sowie Useraccounts und diesen zugeordnete Daten exportiert. Nicht migriert werden Konfigurationsdaten (d.h. im Nuclet enthaltene Objekte) sowie Systeminformationen.
Der Ausdruck -t "^<schema_name>.<nuclet_prefix>*" ist ggf. für jedes Nuclet das Bestandteil der Konfiguration ist zu wiederholen.
...
Den Nuclet-Prefix auf den des Zielsystems anpassen:
| Codeblock | ||
|---|---|---|
| ||
sed -iE "s/<nuclet_prefix>/<nuclet_prefix-zielsystem>/g" my_exported_data.sql |
...
Restliche Daten als INSERT (mit --on-conflict-do-nothing) exportieren:
| Codeblock | ||
|---|---|---|
| ||
/usr/bin/pg_dump --file "more_exported_data.sql" --host "<db host>" --port "<db port>" [--username "<connect with db user>"] [--no-password] --verbose --format=p --blobs --data-only --no-owner --no-privileges --no-tablespaces --no-unlogged-table-data --no-comments --inserts --on-conflict-do-nothing --schema "<schema_name>" -t <schema_name>.t_md_workspace -t "<schema_name>.t_md_preference*" "<schema_name>.t_ud_print*" "<db name>" |
...
...
Auf der Zieldatenbank zunächst temporär alle
...
...
Foreign-Key-Constraints deaktivieren (Skript analog zu Schritt 3 erzeugen), dann importieren:
| Codeblock | ||
|---|---|---|
| ||
psql [-U "<connect with db user>"] -a -v ON_ERROR_STOP=1 -f my_exported_data.sql <DB-name>
psql [-U "<connect with db user>"] -a -v ON_ERROR_STOP=1 -f more_exported_data.sql <DB-name> |
...
Anschließend das documents-Verzeichnis
...
des anderen Systems in das
...
Zielverzeichnis kopieren.
...
...
SQL-Objekte (VLPs, Views, Funktionen
...
, Datenquellen für Reports
...
/Formulare
...
) müssen ggf. händisch angepasst werden – das ist jeweils eine fachliche Frage.