PostgreSQL antipatterns: harc a „halottak” hordáival

A PostgreSQL belső mechanizmusainak sajátosságai lehetővé teszik, hogy bizonyos helyzetekben nagyon gyors, más esetekben „nem túl gyors”. Ma a DBMS működése és a fejlesztői tevékenység közötti konfliktus klasszikus példájára fogunk összpontosítani. UPDATE vs MVCC elvek.

Rövid történet innen remek cikk:

Ha egy sort módosít egy UPDATE paranccsal, akkor valójában két műveletet hajtanak végre: DELETE és INSERT. BAN BEN a karakterlánc aktuális verziója Az xmax értéke megegyezik a FRISSÍTÉST végrehajtó tranzakció számával. Aztán létrejön egy új verzió ugyanaz a sor; az xmin értéke egybeesik az előző verzió xmax értékével.

A tranzakció befejezése után némi idővel a régi vagy az új verzió, attól függően COMMIT/ROOLBACK, felismerik "halott" (halott sorok) elhaladásakor VACUUM táblázat szerint és letisztult.

PostgreSQL antipatterns: harc a „halottak” hordáival

De ez nem fog azonnal megtörténni, de a „halottakkal” kapcsolatos problémák nagyon gyorsan megszerezhetők - ismételt ill rekordok tömeges frissítése egy nagy asztalon, és egy kicsit később ugyanazzal a helyzettel fog találkozni A VACUUM nem fog tudni segíteni.

#1: Szeretem mozgatni

Tegyük fel, hogy a módszered az üzleti logikán dolgozik, és hirtelen rájön, hogy frissíteni kellene az X mezőt valamelyik rekordban:

UPDATE tbl SET X = <newX> WHERE pk = $1;

Aztán a végrehajtás előrehaladtával kiderül, hogy az Y mezőt is frissíteni kell:

UPDATE tbl SET Y = <newY> WHERE pk = $1;

... és akkor Z is - miért vesztegeti az időt apróságokra?

UPDATE tbl SET Z = <newZ> WHERE pk = $1;

Ennek a rekordnak hány verziója van most az adatbázisban? Igen, 4 darab! Ezek közül egy releváns, és 3-at az [auto]VÁKUUM segítségével kell feltakarítania.

Ne csináld így! Használat az összes mező frissítése egy kérelemben — a metódus logikája szinte mindig így változtatható:

UPDATE tbl SET X = <newX>, Y = <newY>, Z = <newZ> WHERE pk = $1;

#2: A használat KÜLÖNBÖZIK, Luke!

Szóval még mindig akartad sok-sok rekord frissítése egy táblázatban (például script vagy konverter használata során). És valami ilyesmi száll be a forgatókönyvbe:

UPDATE tbl SET X = <newX> WHERE pk BETWEEN $1 AND $2;

Meglehetősen gyakran és szinte mindig fordul elő ilyen jellegű kérés, hogy ne egy üres új mezőt töltsön ki, hanem néhány adathibát javítson ki. Ugyanakkor ő maga a meglévő adatok helyességét egyáltalán nem veszik figyelembe - de hiába! Vagyis újraírják a lemezt, még akkor is, ha pontosan azt tartalmazza, amit akartak – de miért? Javítsuk ki:

UPDATE tbl SET X = <newX> WHERE pk BETWEEN $1 AND $2 AND X IS DISTINCT FROM <newX>;

Sokan nincsenek tisztában egy ilyen csodálatos operátor létezésével, ezért itt van egy csalólap IS DISTINCT FROM és egyéb logikai operátorok, amelyek segítenek:
PostgreSQL antipatterns: harc a „halottak” hordáival
... és egy kicsit a komplexen végzett műveletekről ROW()-kifejezések:
PostgreSQL antipatterns: harc a „halottak” hordáival

#3: Felismerem a kedvesemet arról, hogy... blokkolok

elindítják két azonos párhuzamos folyamat, amelyek mindegyike megpróbálja megjelölni a bejegyzést, hogy „folyamatban van”:

UPDATE tbl SET processing = TRUE WHERE pk = $1;

Még akkor is, ha ezek a folyamatok ténylegesen egymástól függetlenül, de ugyanazon az azonosítón belül végeznek dolgokat, a második kliens „le lesz zárva” erre a kérésre az első tranzakció befejezéséig.

1. megoldás: a feladat az előzőre redukálódik

Tegyük hozzá még egyszer IS DISTINCT FROM:

UPDATE tbl SET processing = TRUE WHERE pk = $1 AND processing IS DISTINCT FROM TRUE;

Ebben a formában a második kérés egyszerűen nem változtat semmit az adatbázisban, minden már úgy van, ahogy lennie kell - ezért a blokkolás nem történik meg. Ezután feldolgozzuk a rekord „nem találásának” tényét az alkalmazott algoritmusban.

2. megoldás: tanácsadó zárak

Nagy téma egy külön cikkhez, amiben olvashatsz róla az ajánlási blokkolás alkalmazási módjai és „gereblye”..

3. megoldás: hülye hívások

De pontosan ennek kell történnie veled egyidejű munka ugyanazzal a rekorddal? Vagy elrontottad például az üzleti logika ügyféloldali hívásának algoritmusait? És ha belegondolsz?...

Forrás: will.com

Hozzászólás