Watermarks (watermark)
Die Tabelle watermark ist die Gedächtnisfunktion der DataBridge. Nach jedem
Job-Lauf wird hier gespeichert, bis zu welchem Stand die Daten gelesen wurden.
Beim nächsten Lauf startet der Quellabruf genau an diesem Punkt.
Diese Tabelle wird vom Deployment angelegt und zur Laufzeit automatisch befüllt — manuelle Einträge sind normalerweise nicht nötig. Es gibt jedoch Situationen, in denen ein gezielter Eingriff sinnvoll ist.
Tabellenstruktur
| Spalte | Wert | Beschreibung |
|---|---|---|
| PartitionKey | watermark | Fest vorgegeben — immer watermark |
| RowKey | Jobname | Entspricht dem RowKey des zugehörigen Jobs in der jobs-Tabelle |
| Timestamp | automatisch | Systemseitig gesetzt, nicht bearbeitbar |
| Watermark | Letzter Stand | Format abhängig vom WatermarkType des Jobs (siehe unten) |
| LastCronRun | Zeitstempel | Beginn der letzten Ausführung des Jobs. Basis für die CRON-Intervallprüfung. |
Watermark-Typen
Der Typ wird im Job über das Feld WatermarkType festgelegt und bestimmt,
wie der gespeicherte Wert interpretiert wird.
datetime — Vollständiger Zeitstempel
Für Quellsysteme, die Änderungen über ein Datum-/Uhrzeit-Feld tracken.
Typisch für Business Central (lastModifiedDateTime).
Format: yyyy-MM-ddTHH:mm:ss.fffZ
Beispielwert: 2026-05-31T08:15:00.000Z
Der Filter im Job sieht dann so aus:
{{lastModifiedDateTime gt %watermark%}}
date — Nur Datum
Für Quellsysteme, bei denen nur das Datum (ohne Uhrzeit) relevant ist. Typisch für NAV-Systeme mit datumbasiertem Tracking.
Format: yyyy-MM-dd
Beispielwert: 2026-05-31
string — Change Tracking Token
Für Dataverse / D365CE: Die Change Tracking API gibt bei jedem Abruf einen
opaken Token zurück, der den aktuellen Änderungsstand repräsentiert.
Dieser Token wird als string gespeichert und beim nächsten Lauf direkt
an die API übergeben — kein Datumsvergleich, kein Risiko fehlender Änderungen.
Format: opake Zeichenkette (von Dataverse vergeben)
Beispielwert: 892290!08/10/2026 10:00:00
Für alle D365CE-Jobs WatermarkType = string verwenden. Die Dataverse
Change Tracking API garantiert lückenlose Erkennung aller Änderungen —
auch wenn der Timer während einer Änderung ausgeführt wird.
Schreibweise und unbekannte Typen
Der Typ wird ohne Beachtung von Groß-/Kleinschreibung und ohne umgebende Leerzeichen
erkannt — datetime, DateTime und DATETIME sind gleichwertig.
Steht im Feld WatermarkType ein Wert, der weder date noch datetime noch string
ergibt (z. B. ein Tippfehler), gilt der Typ als unbekannt. Dann passiert Folgendes:
- Die gespeicherte Watermark bleibt unangetastet — sie wird nicht geleert
- Sie wird aber auch nie fortgeschrieben
- Im Log erscheint eine Warnung mit Jobnamen und dem hinterlegten Rohwert
Der Job liest damit bei jedem Lauf dieselbe Menge erneut. Die Warnung im Log ist der einzige Hinweis darauf — es entsteht kein Fehler.
Bis einschließlich v2.0 war das Verhalten deutlich schlimmer: Der Vergleich war
zeichengenau, ein abweichend geschriebenes DateTime leerte die Watermark, und der
Job las bei jedem Lauf das komplette Quellsystem — ohne jede Meldung.
Wann wird der Watermark aktualisiert?
Der Watermark wird am Ende der Erkennungsphase fortgeschrieben — also sobald alle gefundenen Änderungen in die Queue geschrieben sind, und bevor das Zielsystem beschrieben wurde. Für die Zustellung ins Ziel sorgen danach die Queue-Mechanismen (Wiederholung, Dead-Letter).
Im Einzelnen:
- Beim Lesen führt die DataBridge den Änderungsmarker (
ChangeTracker) der verarbeiteten Datensätze mit - Bei
dateunddatetimewird jeweils der höhere der beiden Werte behalten, beistringgewinnt immer der zuletzt gelesene Token — ein opaker Token hat keine Ordnung - Nach dem Leeren des letzten Batches wird der Endstand in die Tabelle geschrieben
LastCronRunwird auf den Zeitpunkt gesetzt, zu dem der Job begonnen hat
Auch dann, wenn der Job keine Änderungen gefunden hat oder gar keinen eigenen Schedule
besitzt. Der Wert ist damit ein verlässlicher Indikator dafür, ob ein Job überhaupt
gelaufen ist.
Bricht ein Job mit einem Fehler ab, bleibt der Watermark auf dem zuletzt geschriebenen Stand. Beim nächsten Lauf wird ab diesem Punkt erneut gelesen.
Zeitzonen
Zeitstempel werden zeitzonenunabhängig verglichen. Bis v2.0 wurde die Zeitangabe in die
lokale Zeit des Servers umgerechnet — beim Typ date konnte das über eine Tagesgrenze
springen und das Vergleichsergebnis je nach Betriebsstandort verändern.
Erster Lauf — kein Eintrag vorhanden
Existiert für einen Job noch kein Watermark-Eintrag, legt die DataBridge ihn beim ersten Lauf automatisch an. Als Startpunkt wird ein möglichst früher Wert verwendet:
| Typ | Initialwert |
|---|---|
datetime | 0001-01-01T00:00:00.000Z |
date | 0001-01-01 |
string | (leer) |
Das bedeutet: der erste Lauf lädt alle vorhandenen Datensätze aus dem Quellsystem. Bei großen Datenmengen sollte dies zu einem Zeitpunkt mit geringer Last geschehen.
Manueller Eingriff — Wann und warum
Die DataBridge schreibt Watermark-Einträge ohne ETag-Prüfung — es gilt Last-Writer-Wins. Wird ein Wert von Hand geändert, während der zugehörige Job gerade läuft, überschreibt der Job die manuelle Änderung am Ende seines Laufs kommentarlos.
Vor einem Eingriff daher die betroffene Funktion deaktivieren
(AzureWebJobs.GetChanges.Disabled = true) oder einen Zeitpunkt wählen, zu dem der Job
nachweislich nicht läuft.
Vollständigen Neulauf erzwingen
Den Wert in der Watermark-Spalte leeren oder auf den Initialwert zurücksetzen.
Beim nächsten Lauf werden alle Datensätze erneut übertragen.
Typische Anwendungsfälle:
- Mapping wurde grundlegend geändert und alle Datensätze sollen neu gemappt werden
- Zielsystem wurde zurückgesetzt oder neu aufgebaut
- Datenverlust im Zielsystem
Partiellen Neulauf ab bestimmtem Datum
Den Watermark-Wert manuell auf ein Datum setzen, ab dem neu gelesen werden soll:
2026-01-01T00:00:00.000Z
Damit werden nur Datensätze übertragen, die seit diesem Datum geändert wurden.
Bei WatermarkType = string ist das nicht möglich — der Token stammt aus Dataverse
und lässt sich nicht sinnvoll von Hand konstruieren. Dort bleibt nur das vollständige
Leeren.
LastCronRun zurücksetzen
Wenn ein Job mit eigenem Schedule nicht zum erwarteten Zeitpunkt ausgeführt wurde,
kann LastCronRun manuell auf einen früheren Wert gesetzt werden. Die DataBridge
erkennt dann, dass das Intervall abgelaufen ist, und führt den Job beim nächsten
Timer-Aufruf aus.