Bemærk
Adgang til denne side kræver godkendelse. Du kan prøve at logge på eller ændre mapper.
Adgang til denne side kræver godkendelse. Du kan prøve at ændre mapper.
Når flere Fabric-notebooks, pipelines eller Spark-jobs skriver til den samme Delta-tabel på samme tid, bruger Delta Lake optimistisk samtidighedskontrol (OCC) for at holde tabellen konsistent. Hver transaktion læser et snapshot, skriver nye filer og validerer derefter, at der ikke skete nogen konfliktfyldt commit imellem. Hvis en konflikt opdages, fejler transaktionen med en undtagelse i stedet for at korrumpere data.
Denne artikel dækker praktiske mønstre til håndtering af samtidige skrivninger i Fabric. For en fuld specifikation af OCC-protokollen, se Delta Lake concurrency control (open source-dokumentation).
Isolationsniveauer
Alle Delta-tabeller bruger Serializable isolationsniveauet. Serializable er det strengeste niveau og det eneste, der understøttes. Den sikrer, at resultatet af samtidige transaktioner er identisk med en sekventiel eksekveringsrækkefølge.
Delta Lake bruger også et internt SnapshotIsolation-niveau til operationer, der ikke ændrer logiske data (såsom OPTIMIZE). SnapshotIsolation springer tjekket af samtidige tilføjelser over, hvilket tillader kompaktering at fortsætte uden at kollidere med samtidige indsættelser. Du konfigurerer ikke SnapshotIsolation direkte – Delta Lake anvender det automatisk, når det er passende.
Med Serializable isolation kan en samtidig blind tilføjelse (INSERT INTO) komme i konflikt med en MERGE eller UPDATE der læser den samme partition.
Hvilke operationer er i konflikt
Ikke alle samtidige skrivninger er i konflikt. Den afgørende faktor er, om to operationer berører de samme underliggende filer.
| Samtidige par | Konflikt? | Hvorfor |
|---|---|---|
To INSERT (tilføjede) operationer |
Nej | Hver tilføjer nye filer uden at læse eksisterende (blind append). |
INSERT + OPTIMIZE |
Nej |
OPTIMIZE commits at SnapshotIsolation , fordi det ikke ændrer logiske data, så det springer cocurrent-append-tjekket helt over. Tilføjelser tilføjer nye filer, der ikke overlapper med filer, der bliver komprimeret. |
To UPDATE, DELETE, eller MERGE operationer |
Ja, hvis de læser eller ændrer overlappende filer | Hver skriver filer om, så den anden forfatters snapshot bliver forældet. |
OPTIMIZE + UPDATE/DELETE/MERGE |
Ja, hvis de rører de samme filer |
OPTIMIZE fjerner og tilføjer filer igen (med dataChange=false). Hvis en dataændringsoperation også læser de samme filer, hæves a ConcurrentDeleteReadException . |
To OPTIMIZE point |
Ja, hvis de vælger de samme filer | Begge forsøger at fjerne og omskrive det samme sæt filer, hvilket udløser en ConcurrentDeleteDeleteException. |
INSERT + MERGE/UPDATE/DELETE |
Ja, hvis dataændringsoperationen læste den samme partition | Under Serializablekan en blind tilføjelse komme i konflikt med samtidige dataændringer, hvis operationen læste en partition, som tilføjelsen skrev til. |
Tip
Append-only pipelines (INSERT INTO, df.write.mode("append")) er den enkleste måde helt at undgå konflikter på. Hvis din arbejdsbyrde kan tilføje først og derefter afstemme, eliminerer du skriv-skriv-konflikt.
Isoler skrivere med opdeling
Den mest almindelige måde at køre samtidig DML mod den samme tabel uden konflikter er at opdele tabellen efter kolonnen, der adskiller dine skrivere, og derefter inkludere den kolonne i hver operationsbetingelse. Når hver writer retter sig mod en forskellig partition, rører operationerne adskilte filsæt og konflikter ikke.
Et typisk scenarie: flere pipelines behandler hver data for en anden forretningsenhed eller lejer. Partitioner efter den dimension og fastgør hver pipeline MERGE til dens 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 *
Vigtigt!
Partitionskolonnen skal vises i selve sammenfletningsbetingelsen – ikke kun i kildedataene. Uden den kan Delta Lake ikke ved validering fastslå, at de to operationer berørte adskilte filsæt, og konflikttjekkeren behandler operationen som en fuldtabellæsning.
For mere detaljer om partitioneringsstrategier, se Partitionering for Delta-tabeller.
Indbygget commit retry
Delta Lake prøver automatisk en commit igen, når den først opdager, at en anden transaktion er blevet gennemført. Ved hvert forsøg læser den den vindende commit, kører konflikttjekkeren, og – hvis der ikke findes nogen logisk konflikt – forsøger den commit igen ved næste tilgængelige version. Denne proces gentages gennemsigtigt uden nogen handling fra din kode.
En logisk konflikt (for eksempel to operationer, der omskriver den samme fil) kan ikke løses automatisk. Omprøvningen rejser en af undtagelserne nævnt i Common conflict-undtagelser. Dog bliver mange transiente versionskollisioner – såsom to blinde tilføjelser, der konkurrerer om samme versionsplads – løst automatisk og vises aldrig i din applikation.
Undtagelser for almindelige konflikter
Når en konflikt opdages, rejser Delta Lake en specifik undtagelse. At forstå, hvilken undtagelse du ser, hjælper med at identificere den egentlige årsag.
| Undtagelse | Hvad skete der |
|---|---|
ConcurrentAppendException |
En anden forfatter tilføjede filer i en partition (eller filsæt), som din operation læste. Almindeligt når en MERGE kører mod en partition, der også modtager inserts fra en anden pipeline. Under Serializable isolation kan selv blinde tilføjelser (almindelige INSERT operationer) udløse denne undtagelse. |
ConcurrentDeleteReadException |
En anden forfatter slettede eller omskrev en fil, som din operation læste. Typisk når OPTIMIZE filer komprimeres, som en samtidig UPDATE eller MERGE også læste, eller når to dataændringsoperationer overlapper på de samme rækker. |
ConcurrentDeleteDeleteException |
Begge operationer forsøgte at slette eller omskrive den samme fil. Ofte forårsaget af overlappende OPTIMIZE kørsler eller to pipelines, der omskriver den samme partition samtidigt. |
ConcurrentWriteException |
En generisk konflikt opstod, når en anden transaktion blev forpligtet til samme tabelversion, før konfliktløsning kunne køre—for eksempel under en filsystem-til-managed-commits-opgradering. |
MetadataChangedException |
Tabelens skema eller egenskaber ændrede sig midt i en transaktion—for eksempel en samtidig ALTER TABLE eller skema-evolution skrivning. |
ConcurrentTransactionException |
To strukturerede streaming-forespørgsler med samme checkpoint-placering blev skrevet til tabellen på samme tid. Afdupliker dine streamingopgaver eller brug forskellige checkpoint-ruter. |
ProtocolChangedException |
En samtidig transaktion opgraderede eller nedgraderede tabelprotokollen, mens den aktuelle transaktion også forsøgte en protokolændring. Kan også opstå, når en tabelfunktion fjernes samtidig. |
Almindelige strategier til at undgå skrivekonflikter
Aktiver automatisk komprimering
Autokomprimering kører synkront som en del af skriveoperationerne. Synkron kompaktering forhindrer, at separat planlagte komprimeringsjobs overlapper med datamodifikationsoperationer og dermed forårsager samtidige writer-undtagelser.
Tidsplanvedligeholdelse uden for skrivevinduer
OPTIMIZE og VACUUM kan komme i konflikt med samtidige datamodifikationsoperationer. I Fabric planlæg notebook-jobs eller pipeline-aktiviteter til table kompaktering og VACUUM under lavaktivitetsvinduer – for eksempel efter natlig indtastning i stedet for under den.
Brug append + merge-mønstre
Ved høj-samtidigheds-indlæsning lander rådata med append-only skrivninger ind i en staging-tabel (ingen konflikter mulige), og kører derefter et enkelt MERGE job for at afstemme i måltabellen. Mønsteret serialiserer den konfliktudsatte operation, mens indtagelsen holdes fuldt parallel.
Tilføj genprøvningslogik for logiske konflikter
Den indbyggede commit retry håndterer automatisk transiente versionskollisioner, men logiske konflikter – hvor to operationer reelt overlapper – skaber en undtagelse. Fordi Delta Lake aldrig producerer delvise skrivninger, er en fejlslagen transaktion sikker at forsøge igen på applikationsniveau. For pipelines, hvor lejlighedsvise logiske konflikter forventes, indpakk skrive-logikken i retry-logikken:
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
Vælg den rigtige layoutstrategi
Væskeklyngedannelse og partitionering løser forskellige problemer. Liquid clustering optimerer fillayoutet for læseydelse. Opdeling skaber fysiske grænser, der forhindrer samtidige konflikter mellem forfattere. Hvis din arbejdsbyrde har brug for begge dele, så partitioner i kolonnen writer-isolation og brug Z-Order inden for hver partition for læseydelse.