Elkülönítési szintek és írási ütközések az Azure Databricksben

A tábla elkülönítési szintje határozza meg, hogy a tranzakciókat milyen mértékben kell elkülöníteni az egyidejű műveletek által végrehajtott módosításoktól. Az Azure Databricks írási ütközései az elkülönítési szinttől függenek.

A Delta Lake ACID-tranzakciós garanciákat biztosít az olvasások és írások között. Ez azt jelenti, hogy:

  • Több fürt több írója egyszerre módosíthatja a táblapartíciókat. Az írók a táblázat konzisztens pillanatkép-nézetét látják, és az írások soros sorrendben történnek.
    • Az olvasók továbbra is egységes pillanatkép-nézetet láthatnak arról a tábláról, amellyel az Azure Databricks-feladat elindult, még akkor is, ha egy tábla módosul egy feladat során.

Tekintse meg az Azure Databricks acid-garanciáit.

Feljegyzés

Az Azure Databricks alapértelmezés szerint az összes táblához használja a Delta Lake-t. Ez a cikk a Delta Lake viselkedését ismerteti az Azure Databricksben.

Fontos

A metaadatok változásai miatt az egyidejű írási műveletek meghiúsulnak. Ezek a műveletek közé tartozik a táblaprotokoll, a táblatulajdonságok vagy az adatséma módosítása.

A streamelési olvasások meghiúsulnak, ha olyan véglegesítést tapasztalnak, amely módosítja a tábla metaadatait. Ha azt szeretné, hogy a stream folytatódjon, újra kell indítania. Az ajánlott módszerekért tekintse meg a strukturált streamelés éles környezettel kapcsolatos szempontjait.

Az alábbi példák a metaadatokat módosító lekérdezésekre mutatnak be példákat:

-- Set a table property.
ALTER TABLE table-name SET TBLPROPERTIES ('delta.isolationLevel' = 'Serializable')

-- Enable a feature using a table property and update the table protocol.
ALTER TABLE table_name SET TBLPROPERTIES ('delta.enableDeletionVectors' = true);

-- Drop a table feature.
ALTER TABLE table_name DROP FEATURE deletionVectors;

-- Upgrade to UniForm.
REORG TABLE table_name APPLY (UPGRADE UNIFORM(ICEBERG_COMPAT_VERSION=2));

-- Update the table schema.
ALTER TABLE table_name ADD COLUMNS (col_name STRING);

Írási ütközések sorszintű egyidejűséggel

A sorszintű egyidejűség csökkenti az egyidejű írási műveletek közötti ütközéseket azáltal, hogy észleli a sorszintű változásokat, és automatikusan feloldja azokat az ütközéseket, amelyek akkor fordulnak elő, amikor az egyidejű írások ugyanazon adatfájl különböző sorait frissítik vagy törlik.

A sorszintű egyidejűség általánosan elérhető a Databricks Runtime 14.2-es és újabb verziókban. A sorszintű egyidejűség alapértelmezés szerint a következő feltételek esetén támogatott:

  • A törlési vektorokkal rendelkező táblák engedélyezve és particionálás nélkül.
  • Folyékony fürtözésű táblák, kivéve, ha letiltotta a törlési vektorokat.

A partíciókat tartalmazó táblák nem támogatják a sorszintű egyidejűséget, de a törlési vektorok engedélyezése esetén továbbra is elkerülhetik az ütközéseket az összes többi írási művelet között OPTIMIZE . Lásd a sorszintű egyidejűség korlátozásait.

Más Databricks Runtime-verziók esetén lásd a sorszintű egyidejűség előnézetének viselkedését (örökölt).

Az alábbi táblázat azt ismerteti, hogy mely írási műveletek párjai ütközhetnek az egyes elkülönítési szinteken a sorszintű egyidejűség engedélyezésével.

Feljegyzés

Az identitásoszlopokat tartalmazó táblák nem támogatják az egyidejű tranzakciókat. Lásd: Identitásoszlopok használata a Delta Lake-ben.

IN Standard kiadás RT (1) FRISSÍTÉS, TÖRLÉS, EGYESÍTÉS OPTIMIZE
INSERT Nem lehet ütközést
FRISSÍTÉS, TÖRLÉS, EGYESÍTÉS A WriteSerializable nem ütközhet. Ütközhet a szerializálhatóban ugyanazon sor módosításakor; lásd a sorszintű egyidejűség korlátozásait. MERGE INTO sorszintű ütközésfeloldáshoz a Photon szükséges. Ütközhet ugyanazon sor módosításakor; lásd a sorszintű egyidejűség korlátozásait.
OPTIMIZE Nem lehet ütközést Nem lehet ütközést Nem lehet ütközést

Fontos

(1) A fenti táblázatokban szereplő összes INSERT művelet olyan hozzáfűző műveleteket ír le, amelyek a véglegesítés előtt nem olvasnak adatokat ugyanabból a táblából. INSERT Azok a műveletek, amelyek ugyanazt a táblát olvasó részlekérdezéseket tartalmaznak, ugyanazt az egyidejűséget támogatják, mint a MERGE.

Ütközések írása sorszintű egyidejűség nélkül

Az alábbi táblázat azt ismerteti, hogy mely írási műveletek párjai ütközhetnek az egyes elkülönítési szinteken.

A táblák nem támogatják a sorszintű egyidejűséget, ha partíciók vannak definiálva, vagy nincsenek engedélyezve a törlési vektorok. A Databricks Runtime 14.2-es vagy újabb verziója szükséges a sorszintű egyidejűséghez.

Feljegyzés

Az identitásoszlopokat tartalmazó táblák nem támogatják az egyidejű tranzakciókat. Lásd: Identitásoszlopok használata a Delta Lake-ben.

IN Standard kiadás RT (1) FRISSÍTÉS, TÖRLÉS, EGYESÍTÉS OPTIMIZE
INSERT Nem lehet ütközést
FRISSÍTÉS, TÖRLÉS, EGYESÍTÉS A WriteSerializable nem ütközhet. Ütközhet a Szerializálhatóban; lásd a partíciókkal való ütközések elkerülését. Ütközhet szerializálható és WriteSerializable; lásd a partíciókkal való ütközések elkerülését.
OPTIMIZE Nem lehet ütközést Nem ütközhet olyan táblákban, amelyekben engedélyezve van a törlési vektor. Máskülönben ütközhet. Nem ütközhet olyan táblákban, amelyekben engedélyezve van a törlési vektor. Máskülönben ütközhet.

Fontos

(1) A fenti táblázatokban szereplő összes INSERT művelet olyan hozzáfűző műveleteket ír le, amelyek a véglegesítés előtt nem olvasnak adatokat ugyanabból a táblából. INSERT Azok a műveletek, amelyek ugyanazt a táblát olvasó részlekérdezéseket tartalmaznak, ugyanazt az egyidejűséget támogatják, mint a MERGE.

A sorszintű egyidejűség korlátozásai

Bizonyos korlátozások a sorszintű egyidejűségre vonatkoznak. Az alábbi műveletek esetében az ütközések feloldása az Azure Databricksen történő írási ütközések normál egyidejűségét követi. Lásd: Írási ütközések sorszintű egyidejűség nélkül.

  • OPTIMIZE parancsok a ZORDER BY.
  • Összetett feltételes záradékokkal rendelkező parancsok, beleértve a következőket:
    • Összetett adattípusok, például szerkezetek, tömbök vagy térképek feltételei.
    • Nem determinisztikus kifejezéseket és al lekérdezéseket használó feltételek.
    • Korrelált alkonyatokat tartalmazó feltételek.
  • Parancsok esetén MERGE explicit predikátumot kell használnia a céltáblán a forrástáblának megfelelő sorok szűréséhez. Az egyesítés feloldása érdekében a szűrővel csak olyan sorokat vizsgálhat, amelyek ütközhetnek az egyidejű műveletek szűrőfeltétele alapján.

Feljegyzés

A sorszintű ütközésészlelés növelheti a teljes végrehajtási időt. Számos egyidejű tranzakció esetén az író rangsorolja a késést az ütközések feloldása és ütközések esetén.

A törlési vektorokra vonatkozó korlátozások is érvényesek. Lásd: Korlátozások.

Mikor véglegesíti a Delta Lake a táblázat olvasása nélkül?

A Delta Lake INSERT - vagy hozzáfűzési műveletek nem olvassák be a tábla állapotát a véglegesítés előtt, ha a következő feltételek teljesülnek:

  1. A logikát SQL-logika vagy hozzáfűzési mód használatával INSERT fejezzük ki.
  2. A logika nem tartalmaz olyan al lekérdezéseket vagy feltételes elemeket, amelyek hivatkoznak az írási művelet által megcélzott táblára.

Más véglegesítésekhez hasonlóan a Delta Lake a tranzakciónapló metaadataival ellenőrzi és feloldja a véglegesítés táblaverzióit, de a tábla egyik verziója sem olvasható be.

Feljegyzés

Számos gyakori minta használ MERGE műveleteket az adatok táblázatfeltételek alapján történő beszúrására. Bár előfordulhat, hogy ezt a logikát utasítások használatával INSERT újraírhatja, ha bármely feltételes kifejezés a céltábla egyik oszlopára hivatkozik, ezek az utasítások ugyanolyan egyidejűségi korlátozásokkal rendelkeznek, mint MERGEa .

Szerializálható és szerializálható elkülönítési szintek írása

A tábla elkülönítési szintje határozza meg, hogy a tranzakciókat milyen mértékben kell elkülöníteni az egyidejű tranzakciók által végrehajtott módosításoktól. Az Azure Databricks Delta Lake két elkülönítési szintet támogat: szerializálható és WriteSerializable.

  • Szerializálható: A legerősebb elkülönítési szint. Biztosítja, hogy a véglegesített írási műveletek és az összes olvasás szerializálható legyen. A műveletek akkor engedélyezettek, ha létezik olyan sorozat, amely egyenként hajtja végre őket, és ugyanazt az eredményt hozza létre, mint a táblában. Az írási műveletek esetében a sorozatszám pontosan megegyezik a táblázat előzményeiben látottakéval.

  • WriteSerializable (Alapértelmezett): A szerializálhatónál gyengébb elkülönítési szint. Csak azt biztosítja, hogy az írási műveletek (vagyis nem az olvasások) szerializálhatók legyenek. Ez azonban még mindig erősebb, mint a Pillanatkép elkülönítése. A WriteSerializable az alapértelmezett elkülönítési szint, mivel nagy adatkonzisztenciát és rendelkezésre állást biztosít a leggyakoribb műveletekhez.

    Ebben a módban a Delta-tábla tartalma eltérhet a táblaelőzményekben látható műveletek sorozatától. Ennek az az oka, hogy ez a mód lehetővé teszi bizonyos párhuzamos írási párok (például az X és az Y műveletek) folytatását, hogy az eredmény olyan legyen, mintha az Y-t X előtt hajtották volna végre (vagyis szerializálható közöttük), annak ellenére, hogy az előzmények azt mutatják, hogy az Y véglegesítése az X után történt. Az átrendezés letiltásához állítsa a táblaelkülönítési szintet szerializálhatóra, hogy a tranzakciók meghiúsuljanak.

Az olvasási műveletek mindig pillanatkép-elkülönítést használnak. Az íráselkülönítési szint határozza meg, hogy az olvasó láthat-e egy táblázat pillanatképét, amely az előzmények szerint "soha nem létezett".

A Szerializálható szint esetében az olvasó mindig csak az előzményeknek megfelelő táblákat látja. A WriteSerializable szint esetében az olvasó olyan táblát láthat, amely nem létezik a Delta-naplóban.

Vegyük például a txn1-et, egy hosszú ideig futó törlést és txn2-t, amely a txn1 által törölt adatokat szúrja be. txn2 és txn1 kész, és az előzményekben ebben a sorrendben vannak rögzítve. Az előzmények szerint a txn2-be beszúrt adatok nem létezhetnek a táblában. Szerializálható szint esetén az olvasó soha nem látja a txn2 által beszúrt adatokat. A WriteSerializable szint esetében azonban az olvasó egy bizonyos ponton láthatta a txn2 által beszúrt adatokat.

További információ arról, hogy az egyes elkülönítési szinteken milyen típusú műveletek ütközhetnek egymással, valamint a lehetséges hibákról lásd : Ütközések elkerülése particionálás és különálló parancsfeltételek használatával.

Az elkülönítési szint beállítása

Az elkülönítési szintet a ALTER TABLE paranccsal állíthatja be.

ALTER TABLE <table-name> SET TBLPROPERTIES ('delta.isolationLevel' = <level-name>)

hol <level-name> van vagy WriteSerializableSerializable .

Ha például az elkülönítési szintet alapértelmezettről az alapértelmezettre WriteSerializable szeretné módosítani, futtassa a következőt Serializable:

ALTER TABLE <table-name> SET TBLPROPERTIES ('delta.isolationLevel' = 'Serializable')

Az ütközések elkerülése particionálással és a parancsfeltételek szétválasztásával

A "can conflict" (Ütközés lehet) jelölésű összes esetben attól függ, hogy a két művelet ütközik-e, attól függ, hogy ugyanazon a fájlkészleten működnek-e. A két fájlhalmazt úgy lehet különállóvá tenni, hogy a táblát a műveletek feltételeiben használt oszlopokkal azonos oszlopokkal particionálja. A két parancs UPDATE table WHERE date > '2010-01-01' ...DELETE table WHERE date < '2010-01-01' például ütközik, ha a tábla nincs dátum szerint particionálva, mivel mindkettő megpróbálhatja módosítani ugyanazt a fájlkészletet. A tábla date particionálása elkerüli az ütközést. Ezért a parancsban gyakran használt feltételeknek megfelelő táblák particionálása jelentősen csökkentheti az ütközéseket. A táblák magas számosságú oszlop szerinti particionálása azonban a nagy számú alkönyvtár miatt más teljesítményproblémákhoz vezethet.

Ütközési kivételek

Ha a tranzakciók ütköznek, a következő kivételek egyikét fogja látni:

ConcurrentAppendException

Ez a kivétel akkor fordul elő, amikor egy párhuzamos művelet fájlokat ad hozzá ugyanabban a partícióban (vagy bárhol egy partícionálatlan táblában), amelyet a művelet olvas. A fájl hozzáadását okozhatja INSERTa , DELETE, UPDATEvagy MERGE a műveletek.

A vakműveletekINSERT által hozzáadott fájlok (vagyis az adatok olvasása nélkül vakon hozzáfűző műveletek) alapértelmezett elkülönítési WriteSerializableszintje nem ütközik semmilyen művelettel, még akkor sem, ha ugyanahhoz a partícióhoz (vagy egy nem particionált táblához) érnek. Ha az elkülönítési szint be van állítva Serializable, akkor a vak hozzáfűzők ütközhetnek.

Ez a kivétel gyakran egyidejű DELETE, UPDATEvagy MERGE műveletek során jelentkezik. Bár a párhuzamos műveletek fizikailag különböző partíciókönyvtárakat frissíthetnek, az egyik beolvashatja ugyanazt a partíciót, amelyet a másik párhuzamosan frissít, ezzel ütközést okozva. Ezt úgy kerülheti el, ha explicit módon határozza meg az elkülönítést a műveleti feltételben. Gondolja át a következő példát.

// Target 'deltaTable' is partitioned by date and country
deltaTable.as("t").merge(
    source.as("s"),
    "s.user_id = t.user_id AND s.date = t.date AND s.country = t.country")
  .whenMatched().updateAll()
  .whenNotMatched().insertAll()
  .execute()

Tegyük fel, hogy a fenti kódot párhuzamosan futtatja különböző dátumok vagy országok esetében. Mivel minden feladat egy független partíción dolgozik a cél Delta-táblán, nem számít ütközésekre. A feltétel azonban nem elég explicit, és a teljes táblát átvizsgálhatja, és ütközhet a többi partíció egyidejű frissítésével. Ehelyett átírhatja az utasítást, hogy adott dátumot és országot adjon hozzá az egyesítési feltételhez, ahogy az az alábbi példában is látható.

// Target 'deltaTable' is partitioned by date and country
deltaTable.as("t").merge(
    source.as("s"),
    "s.user_id = t.user_id AND s.date = t.date AND s.country = t.country AND t.date = '" + <date> + "' AND t.country = '" + <country> + "'")
  .whenMatched().updateAll()
  .whenNotMatched().insertAll()
  .execute()

Ez a művelet mostantól biztonságosan futtatható egyidejűleg különböző dátumokon és országokban.

ConcurrentDeleteReadException

Ez a kivétel akkor fordul elő, ha egy egyidejű művelet törölt egy fájlt, amelyet a művelet beolvasott. A gyakori okok a DELETEfájlok átírására irányuló műveletekUPDATEMERGE.

ConcurrentDeleteDeleteException

Ez a kivétel akkor fordul elő, ha egy egyidejű művelet törölt egy fájlt, amelyet a művelet is töröl. Ezt okozhatja két egyidejű tömörítési művelet, amely ugyanazokat a fájlokat írja át.

MetadataChangedException

Ez a kivétel akkor fordul elő, ha egy egyidejű tranzakció frissíti egy Delta-tábla metaadatait. Gyakori okok a ALTER TABLE deltatáblába írt műveletek vagy írások, amelyek frissítik a tábla sémáját.

ConcurrentTransactionException

Ha egy azonos ellenőrzőpont-helyet használó streamlekérdezés egyszerre többször is elindul, és egyszerre próbál meg írni a Delta táblába. Soha nem szabad, hogy két streamelési lekérdezés ugyanazt az ellenőrzőpont-helyet használja, és egyszerre fusson.

ProtocolChangedException

Ez a kivétel a következő esetekben fordulhat elő:

  • Amikor a Delta-tábla új protokollverzióra frissül. A jövőbeli műveletek sikerességéhez szükség lehet a Databricks-futtatókörnyezet frissítésére.
  • Ha egyszerre több író is létrehoz vagy cserél egy táblát.
  • Ha egyszerre több író is egy üres útvonalra ír.

További információ: Hogyan kezeli az Azure Databricks a Delta Lake szolgáltatáskompatibilitását?

Sorszintű egyidejűség előnézetének viselkedése (örökölt)

Ez a szakasz a Databricks Runtime 14.1-es és újabb verziójában a sorszintű egyidejűség előnézeti viselkedését ismerteti. A sorszintű egyidejűség mindig törlési vektorokat igényel.

A Databricks Runtime 13.3 LTS és újabb verziókban a folyékony fürtözést engedélyező táblák automatikusan engedélyezik a sorszintű egyidejűséget.

A Databricks Runtime 14.0-s és 14.1-es verziójában engedélyezheti a sorszintű egyidejűséget a törlési vektorokkal rendelkező táblák esetében a fürt vagy a SparkSession következő konfigurációjának beállításával:

spark.databricks.delta.rowLevelConcurrencyPreview = true

A Databricks Runtime 14.1-es és újabb verzióban a nem Foton-számítás csak a sorszintű egyidejűséget támogatja a műveletekhez DELETE .