Worum es geht
In MULTI hat jeder Mandant eine eigene Datenbank. Zu jeder Datenbank gehören drei Dinge, die CDMS verwaltet:
- die Datenbank selbst, mit dem Mandantenschlüssel als Namen,
- ihr Schema, also die Tabellen der Modelle,
- ein Verbindungspool. Das ist ein Vorrat an offenen Verbindungen zur Datenbank, die sich die Anfragen ausleihen, statt jedes Mal eine neue aufzubauen.
Dazu kommt für jedes Ziel ein Objekt, das Hibernate zum Arbeiten braucht: die EntityManagerFactory. Sie kennt die Modelle des Ziels und wird beim ersten Zugriff gebaut. Mit ihr entstehen auch Pool und Schema.
Der Lebenslauf eines Persistenzziels
-
1CDMSerster Zugriff auf Mandant
acmeseit dem Start, oder CIAS stelltacmebereit -
2CDMS→Databasefragt den Datenbankserver: Gibt es die Datenbank
acme? -
3CDMS→Databasefehlt sie und ist Anlegen freigegeben →
CREATE DATABASE acme -
4CDMSbaut den Verbindungspool für
acme -
5CDMS→Databasebringt das Schema auf den aktuellen Stand
-
6CDMSbaut die EntityManagerFactory mit den Mandanten- und Benutzer-ModellenErgebnis: Ab jetzt nutzen alle Anfragen von
acmePool und Factory, bis sie geräumt werden.
Wann die Datenbank angelegt wird
Es gibt zwei Wege, die zum selben Ergebnis führen:
Wann: CIAS läuft in derselben Anwendung wie CDMS und legt den Mandanten an.
-
1CIASlegt den Mandanten
acmean -
2CIAS→CDMSbittet um Bereitstellung von
acme -
3CDMS→Databaselegt Datenbank und Schema an, wie oben beschrieben
Ergebnis: Scheitert das, erfährt es der Betrieb beim Anlegen des Kunden und nicht der Kunde bei seiner ersten Anfrage. Das Anlegen lässt sich gefahrlos wiederholen.
Wann: CIAS läuft als eigener Dienst, oder die Bereitstellung wurde übersprungen.
-
1Client→CDMSerste Anfrage für
acme -
2CDMS→Databaselegt Datenbank und Schema an, wie oben beschrieben
Ergebnis: Die erste Anfrage dauert länger. Scheitert die Anlage, bekommt diese Anfrage den Fehler.
Wann: CODAMAI_PERSISTENCE_TENANT_MODE=SINGLE
Es gibt nur die eine Datenbank. Eine Bereitstellung je Mandant hat nichts zu tun und meldet sofort Erfolg.
Ergebnis: Die eine Datenbank muss es geben oder sie wird beim Start wie oben angelegt.
| Datenbankserver erreichbar | Datenbank vorhanden | Anlegen freigegeben | Ergebnis |
|---|---|---|---|
| ja | ja | – | Datenbank wird benutzt |
| ja | nein | ja | Datenbank wird angelegt und benutzt |
| ja | nein | nein | 500 CDMS_TENANT_DATASOURCE_NOT_FOUND |
| nein | – | – | 503 CDMS_TENANT_DATASOURCE_UNAVAILABLE, kein Anlegeversuch |
Die Freigabe ist CODAMAI_PERSISTENCE_DATABASE_AUTO_CREATE_TENANT_DATABASE=true. Ohne sie legt der Betrieb jede Mandanten-Datenbank selbst an. Ein nicht erreichbarer Server gilt nie als „Datenbank fehlt“. Sonst würde ein kurzer Ausfall eine Anlage auslösen.
Automatisch anlegen kann CDMS Datenbanken auf MySQL, mit Zeichensatz utf8mb4. Direkt vor dem CREATE DATABASE prüft CDMS den Namen noch einmal: nur Kleinbuchstaben, Ziffern und Bindestriche.
Das Schema migrieren
Migrieren heißt: die Tabellen einer Datenbank an den Stand der Modelle anpassen, etwa eine neue Spalte anlegen. Jede Datenbank wird einzeln migriert, und zwar dann, wenn CDMS ihre EntityManagerFactory baut. Das ist nach jedem Start beim ersten Zugriff auf den Mandanten der Fall.
- Hibernate vergleicht Modelle und Tabellen und ergänzt, was fehlt
- ergänzt Tabellen und Spalten, löscht und benennt nichts um
- keine Versionen, kein Protokoll in der Datenbank
CODAMAI_PERSISTENCE_DATABASE_AUTO_UPDATE=falseschaltet das Ergänzen ab; dann prüft Hibernate nur
- SQL-Skripte mit Versionsnummer, in der Anwendung mitgeliefert
- eigene Ordner für System-Datenbank und Mandanten-Datenbanken
- jede Datenbank führt ihr eigenes Protokoll, bekommt also nur die fehlenden Skripte
- Hibernate prüft danach nur noch, ob Tabellen und Modelle passen
Welche Art gilt, steht in CDMS_DATABASE_MIGRATION_MODE (HIBERNATE oder FLYWAY). Die Skripte liegen standardmäßig unter db/migration/system und db/migration/tenant.
System-Datenbank und Mandanten-Datenbanken kennen verschiedene Modelle: die System-Datenbank nur System-Modelle, eine Mandanten-Datenbank nur Mandanten- und Benutzer-Modelle. Nur die Tabelle der Revisionen, die die Historie braucht, gibt es in jeder Datenbank.
Verbindungspools
Jedes Ziel hat seinen eigenen Pool. Bei hundert Mandanten sind das hundert Pools. Damit sie zusammen den Datenbankserver nicht überlasten, halten sie in MULTI im Leerlauf keine Verbindungen offen.
| Einstellung | Standard | Bedeutung |
|---|---|---|
CODAMAI_PERSISTENCE_DATABASE_POOL_SIZE | 20 | höchstens so viele Verbindungen je Pool |
CODAMAI_PERSISTENCE_DATABASE_POOL_MIN_IDLE | abgeleitet | Verbindungen, die im Leerlauf offen bleiben: in MULTI 0, in SINGLE so viele wie die Pool-Größe |
CODAMAI_PERSISTENCE_DATABASE_POOL_IDLE_TIMEOUT_SECONDS | 600 | nach so vielen Sekunden ohne Nutzung wird eine überzählige Verbindung geschlossen |
Eine Anfrage leiht sich in der Regel je berührter Datenbank eine Verbindung und gibt sie am Ende der Anfrage zurück.
Ungenutzte Mandanten räumen
CDMS hält nicht für jeden Mandanten dauerhaft Factory und Pool bereit. Es räumt sie weg, wenn sie länger nicht gebraucht wurden:
| Einstellung | Standard | Bedeutung |
|---|---|---|
CODAMAI_PERSISTENCE_DATABASE_FACTORY_CACHE_SIZE | 100 | höchstens so viele Mandanten gleichzeitig bereit; darüber hinaus wird der am längsten ungenutzte geräumt |
CODAMAI_PERSISTENCE_DATABASE_FACTORY_CACHE_IDLE_SECONDS | 1800 | nach so vielen Sekunden ohne Zugriff wird ein Mandant geräumt; 0 schaltet das ab |
Geräumt heißt: Neue Anfragen bauen Factory und Pool neu auf, samt Migrationsprüfung. Laufende Anfragen arbeiten ungestört zu Ende. Geschlossen wird erst, wenn die letzte von ihnen fertig ist. Die System-Datenbank und die Datenbank von SINGLE werden nie geräumt.
Fallen
Wie es weitergeht
- Wann welche Datenbank gewählt wird: Welche Datenbank? Das Persistenzziel
- Ein neuer Mandant über beide Module: Ein neuer Mandant, Ende zu Ende
- Wie die Schemata beider Module zusammenpassen: Datenbanken und Schemata