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).
MERGE INTO
A sorszintű egyidejűség támogatásához a Photon szükséges a Databricks Runtime 14.2-ben. A Databricks Runtime 14.3 LTS-ben és újabb verziókban a Photon nem szükséges.
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.
INSERT (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. | Ütközhet ugyanazon sor módosításakor. Lásd a sorszintű egyidejűség korlátozásait. | |
OPTIMIZE | Nem lehet ütközést | Ütközést okozhat a használat során ZORDER BY . Másként nem ütközhet. |
Ütközést okozhat a használat során ZORDER BY . Másként nem ü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
.
REORG
a műveletek elkülönítési szemantikája megegyezik az OPTIMIZE
adatfájlok újraírásakor a törlési vektorokban rögzített változásoknak megfelelően. Frissítés REORG
alkalmazásakor megváltoznak a táblaprotokollok, amelyek ütköznek az összes folyamatban lévő művelettel.
Ü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.
INSERT (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ó fájlban. Tekintse meg a partíciókkal való ütközések elkerülését. | Ütközhet a Szerializálható és a WriteSerializable fájlban. Tekintse meg a partíciókkal való ütközések elkerülését. | |
OPTIMIZE | Nem lehet ütközést | A törlési vektorokat engedélyező táblákban csak akkor lehet ütközni, ha ZORDER BY nincs használatban. Máskülönben ütközhet. |
A törlési vektorokat engedélyező táblákban csak akkor lehet ütközni, ha ZORDER BY nincs használatban. 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
.
REORG
a műveletek elkülönítési szemantikája megegyezik az OPTIMIZE
adatfájlok újraírásakor a törlési vektorokban rögzített változásoknak megfelelően. Frissítés REORG
alkalmazásakor megváltoznak a táblaprotokollok, amelyek ütköznek az összes folyamatban lévő művelettel.
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.
- Ö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.
- A Databricks Runtime 14.2-ben
MERGE
a parancsoknak explicit predikátumot kell használniuk 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ő csak olyan sorokat vizsgál, amelyek ütközhetnek az egyidejű műveletek szűrőfeltételei 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:
- A logikát SQL-logika vagy hozzáfűzési mód használatával
INSERT
fejezzük ki. - 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 MERGE
a .
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 WriteSerializable
Serializable
.
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 INSERT
a , DELETE
, UPDATE
vagy MERGE
a műveletek.
A vakműveletek INSERT
á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 WriteSerializable
szintje 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
, UPDATE
vagy 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 DELETE
fájlok átírására irányuló műveletekUPDATE
MERGE
.
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
.