Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Wenn mehrere Fabric Notizbücher, Pipelines oder Spark-Aufträge gleichzeitig in dieselbe Delta-Tabelle schreiben, verwendet Delta Lake optimistische Parallelitätssteuerung (OCC), um die Tabelle konsistent zu halten. Jede Transaktion liest eine Momentaufnahme, schreibt neue Dateien und überprüft dann, ob kein konfliktierender Commit dazwischen aufgetreten ist. Wenn ein Konflikt erkannt wird, schlägt die Transaktion mit einer Ausnahme und nicht mit beschädigten Daten fehl.
In diesem Artikel werden praktische Muster für die Verwaltung gleichzeitiger Schreibvorgänge in Fabric behandelt. Eine vollständige Spezifikation des OCC-Protokolls finden Sie in der Dokumentation zur Parallelität von Delta Lake (Open-Source-Dokumentation).
Isolationsebenen
Alle Delta-Tabellen verwenden die serialisierbare Isolationsebene. Serialisierbar ist die strengste Ebene und die einzige unterstützte. Es stellt sicher, dass das Ergebnis gleichzeitiger Transaktionen mit einer sequenziellen Ausführungsreihenfolge identisch ist.
Delta Lake verwendet auch eine interne SnapshotIsolation-Ebene für Vorgänge, die logische Daten nicht ändern (z. B OPTIMIZE. ). SnapshotIsolation überspringt die Prüfung auf konkurrierendes Anhängen, sodass die Kompaktierung fortgesetzt werden kann, ohne mit konkurrierenden Einfügungen in Konflikt zu geraten. Sie konfigurieren SnapshotIsolation nicht direkt – Delta Lake wendet es bei Bedarf automatisch an.
Bei Serializable-Isolation kann ein gleichzeitiges blindes Anhängen (INSERT INTO) mit einem MERGE oder UPDATE in Konflikt geraten, das dieselbe Partition liest.
Welche Vorgänge stehen in Konflikt
Nicht alle gleichzeitigen Schreibvorgänge verursachen Konflikte. Der Schlüsselfaktor ist, ob zwei Vorgänge die gleichen zugrunde liegenden Dateien berühren.
| Paralleles Paar | Konflikt? | Warum? |
|---|---|---|
Zwei INSERT (Anfügevorgänge) |
No | Jede fügt neue Dateien hinzu, ohne vorhandene dateien zu lesen (blindes Anfügen). |
INSERT + OPTIMIZE |
No |
OPTIMIZE führt bei SnapshotIsolation das Commit aus, da es die logischen Daten nicht ändert und daher die Prüfung auf gleichzeitiges Anhängen vollständig überspringt. Fügt neue Dateien hinzu, die sich nicht mit komprimierten Dateien überlappen. |
Zwei UPDATE, DELETE oder MERGE Vorgänge |
Ja, wenn sie überlappende Dateien lesen oder ändern | Jeder überschreibt Dateien, sodass der Snapshot des zweiten Schreibers veraltet ist. |
OPTIMIZE + UPDATE/DELETE/MERGE |
Ja, wenn sie dieselben Dateien berühren |
OPTIMIZE entfernt und liest Dateien (mit dataChange=false). Wenn ein Datenänderungsvorgang auch dieselben Dateien liest, wird eine ConcurrentDeleteReadException ausgelöst. |
Zwei OPTIMIZE Läufe |
Ja, wenn sie die gleichen Dateien auswählen | Beide versuchen, dieselbe Gruppe von Dateien zu entfernen und neu zu schreiben, wodurch ein ConcurrentDeleteDeleteException ausgelöst wird. |
INSERT + MERGE/UPDATE/DELETE |
Ja, wenn der Datenänderungsvorgang dieselbe Partition liest | Unter Serializablekann eine blinde Anfüge mit gleichzeitigen Datenänderungen in Konflikt geraten, wenn der Vorgang eine Partition liest, an die die Anfüge geschrieben wurde. |
Tipp
Pipelines nur mit Anhängen (INSERT INTO, df.write.mode("append")) sind der einfachste Weg, Konflikte vollständig zu vermeiden. Wenn Ihre Workload zunächst anhängen und später abgleichen kann, vermeiden Sie Schreib-Schreib-Konflikte.
Isolieren von Autoren mit Partitionierung
Die am häufigsten verwendete Methode zum Ausführen gleichzeitiger DML für dieselbe Tabelle ohne Konflikte besteht darin, die Tabelle nach der Spalte zu partitionieren , die Ihre Autoren trennt, und diese Spalte dann in jede Vorgangsbedingung einschließen. Wenn jeder Writer auf eine andere Partition ausgerichtet ist, berühren die Vorgänge nicht zusammenhängende Dateisätze und führen keinen Konflikt.
Ein typisches Szenario: mehrere Pipelines verarbeiten jeweils Daten für eine andere Geschäftseinheit oder einen anderen Mandanten. Unterteilen Sie nach dieser Dimension und fixieren Sie die MERGE jeder Pipeline in der jeweiligen Partition.
-- Each pipeline targets its own partition, so concurrent runs don't conflict
MERGE INTO events AS target
USING staged AS source
ON target.event_id = source.event_id
AND target.business_unit = 'EMEA'
WHEN MATCHED THEN UPDATE SET *
WHEN NOT MATCHED THEN INSERT *
Important
Die Partitionsspalte muss in der Zusammenführungsbedingung selbst angezeigt werden , nicht nur in den Quelldaten. Ohne dies kann Delta Lake bei der Validierung nicht feststellen, dass die beiden Vorgänge auf disjunkte Dateimengen zugegriffen haben, und die Konfliktprüfung behandelt den Vorgang als vollständigen Lesezugriff auf die gesamte Tabelle.
Weitere Informationen zu Partitionierungsstrategien finden Sie unter Partitionierung für Delta-Tabellen.
Integrierte Commit-Wiederholung
Delta Lake wiederholt einen Commit automatisch, wenn erkannt wird, dass eine andere Transaktion zuerst festgeschrieben wurde. Bei jedem Wiederholungsversuch liest er den maßgeblichen Commit, führt die Konfliktprüfung aus und versucht den Commit – sofern kein logischer Konflikt vorliegt – mit der nächsten verfügbaren Version erneut. Dieser Vorgang wiederholt sich automatisch, ohne dass Ihr Code etwas dafür tun muss.
Ein logischer Konflikt (z. B. zwei Vorgänge, die dieselbe Datei umschreiben) können nicht automatisch aufgelöst werden. Der Wiederholungsversuch löst eine der in Allgemeine Konfliktausnahmen aufgeführten Ausnahmen aus. Allerdings werden viele vorübergehende Versionskonflikte – etwa wenn zwei blinde Append-Vorgänge um denselben Versionsslot konkurrieren – automatisch aufgelöst und Ihrer Anwendung niemals angezeigt.
Häufige Konflikt ausnahmen
Wenn ein Konflikt erkannt wird, löst Delta Lake eine bestimmte Ausnahme aus. Verstehen, welche Ausnahme Sie sehen, hilft ihnen, die Ursache zu identifizieren.
| Exception | Was ist passiert |
|---|---|
ConcurrentAppendException |
Ein anderer Schreibvorgang hat Dateien zu einer Partition (oder einem Dateisatz) hinzugefügt, die Ihr Vorgang gelesen hat. Üblich, wenn MERGE für eine Partition ausgeführt wird, in die auch von einer anderen Pipeline Einfügungen vorgenommen werden. Bei Serializable-Isolation kann selbst blindes Anhängen (einfache INSERT-Operationen) diese Ausnahme auslösen. |
ConcurrentDeleteReadException |
Ein anderer Schreibvorgang hat eine Datei gelöscht oder neu geschrieben, die Ihr Vorgang gelesen hat. Typisch, wenn OPTIMIZE Dateien komprimiert, die gleichzeitig auch von UPDATE oder MERGE gelesen wurden, oder wenn sich zwei Datenänderungsvorgänge bei denselben Zeilen überschneiden. |
ConcurrentDeleteDeleteException |
Beide Vorgänge haben versucht, dieselbe Datei zu löschen oder umzuschreiben. Häufig verursacht durch überlappende OPTIMIZE Ausführungen oder zwei Pipelines, die dieselbe Partition gleichzeitig umschreiben. |
ConcurrentWriteException |
Ein allgemeiner Konflikt, der auftritt, wenn eine andere Transaktion für dieselbe Tabellenversion committet wurde, bevor die Konfliktauflösung ausgeführt werden konnte – zum Beispiel während eines Upgrades von Dateisystem- auf verwaltete Commits. |
MetadataChangedException |
Das Tabellenschema oder die Eigenschaften wurden während der Transaktion geändert – zum Beispiel durch einen gleichzeitigen ALTER TABLE-Schreibvorgang oder einen Schreibvorgang zur Schemaänderung. |
ConcurrentTransactionException |
Zwei Structured-Streaming-Abfragen mit demselben Checkpoint-Speicherort haben gleichzeitig in die Tabelle geschrieben. Deduplizieren Sie Ihre Streamingaufträge, oder verwenden Sie unterschiedliche Prüfpunktpfade. |
ProtocolChangedException |
Eine gleichzeitige Transaktion hat das Tabellenprotokoll aktualisiert oder herabgestuft, während die aktuelle Transaktion auch eine Protokolländerung versucht hat. Kann auch auftreten, wenn eine Tabellenfunktion gleichzeitig gelöscht wird. |
Häufige Strategien zum Vermeiden von Schreibkonflikten
Automatische Komprimierung aktivieren
Die automatische Komprimierung wird synchron als Teil von Schreibvorgängen ausgeführt. Die synchrone Komprimierung verhindert, dass separat geplante Komprimierungsaufträge mit Datenänderungsvorgängen überlappen und somit gleichzeitige Writer-Ausnahmen verursachen.
Planen der Wartung außerhalb von Schreibfenstern
OPTIMIZE und VACUUM können mit gleichzeitigen Vorgängen zur Datenänderung in Konflikt geraten. Planen Sie in Fabric Notebook-Aufträge oder Pipelineaktivitäten für Tabellenkomprimierung und VACUUM für Zeiten mit geringer Aktivität ein, z. B. nach Abschluss der nächtlichen Datenerfassung und nicht während der Datenerfassung.
Muster zum Anfügen und Zusammenführen verwenden
Für die Datenaufnahme mit hoher Parallelität legen Sie Rohdaten per ausschließlich anhängenden Schreibvorgängen in einer Staging-Tabelle ab (Konflikte sind dabei ausgeschlossen) und führen anschließend einen einzelnen MERGE-Job aus, um die Daten mit der Zieltabelle abzugleichen. Das Muster serialisiert den konfliktanfälligen Vorgang bei weiterhin vollständig paralleler Datenaufnahme.
Hinzufügen von Wiederholungslogik für logische Konflikte
Der integrierte Commit-Wiederholungsmechanismus behandelt transiente Versionskonflikte automatisch, aber logische Konflikte – bei denen sich zwei Vorgänge tatsächlich überschneiden – führen zu einer Ausnahme. Da Delta Lake niemals partielle Schreibvorgänge erzeugt, kann eine fehlgeschlagene Transaktion auf Anwendungsebene gefahrlos wiederholt werden. Für Pipelines, bei denen gelegentlich logische Konflikte zu erwarten sind, kapseln Sie den Schreibvorgang in eine Retry-Logik:
from delta.exceptions import ConcurrentAppendException
import time
# Retry with backoff on transient concurrent write conflicts
max_retries = 3
for attempt in range(max_retries):
try:
spark.sql("MERGE INTO target USING source ON ...")
break
except ConcurrentAppendException:
if attempt < max_retries - 1:
time.sleep(2 ** attempt)
else:
raise
Auswählen der richtigen Layoutstrategie
Flüssigkeitsclustering und Partitionierung lösen verschiedene Probleme. Das Flüssige Clustering optimiert das Dateilayout für die Leseleistung. Die Partitionierung erstellt physische Grenzen, die gleichzeitige Schreibkonflikte verhindern. Wenn Ihr Workload beides erfordert, partitionieren Sie nach der Writer-Isolationsspalte und verwenden Sie innerhalb jeder Partition Z-Order zur Verbesserung der Leseleistung.