PostgreSQL Antipatterns: kæmper mod horder af "døde"

Den måde PostgreSQL's interne mekanismer fungerer på gør, at den er meget hurtig i nogle situationer og "ikke så hurtig" i andre. I dag vil vi fokusere på et klassisk eksempel på en konflikt mellem, hvordan et DBMS fungerer, og hvad en udvikler gør med det - OPDATERING vs MVCC principper.

Kort plot fra stor artikel:

Når en række ændres af en UPDATE-kommando, udføres der faktisk to operationer: DELETE og INSERT. I nuværende version af linjen xmax er indstillet til nummeret på den transaktion, der udførte OPDATERING. Så er det skabt en ny version samme linje; dens xmin-værdi er den samme som xmax-værdien i den tidligere version.

Nogen tid efter denne transaktion er gennemført, den gamle eller nye version, afhængigt af COMMIT/ROOLBACK, vil blive anerkendt "død" (døde tupler) når man passerer VACUUM i henhold til tabellen og ryddet.

PostgreSQL Antipatterns: kæmper mod horder af "døde"

Men dette vil ikke ske med det samme, men problemer med de "døde" kan erhverves meget hurtigt - med gentagne eller masseopdatering af poster i et stort bord, og lidt senere støde på en situation, der VACUUM vil ikke være i stand til at hjælpe.

#1: Jeg kan godt lide at flytte den

Lad os sige, at din forretningslogikmetode virker og pludselig indser, at den skal opdatere felt X i en eller anden post:

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

Efterhånden som udførelsen skrider frem, finder den ud af, at Y-feltet også skal opdateres:

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

... og så er der også Z – hvorfor bøvle med småting?

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

Hvor mange versioner af denne post har vi nu i databasen? Ja, 4 stk! Af disse er den ene relevant, og de tre andre skal renses op med [auto]VACUUM.

Gør det ikke! Bruge opdatere alle felter i én anmodning — næsten altid logikken i metoden kan ændres sådan:

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

#2: Brug ER DISTILT FRA, Luke!

Så det ville du stadig gerne opdatere mange mange poster i en tabel (under brug af f.eks. et script eller konverter). Og noget som dette flyver ind i manuskriptet:

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

En anmodning i omtrent denne form støder på ret ofte og næsten altid for ikke at udfylde et tomt nyt felt, men for at rette nogle fejl i dataene. Samtidig er hun selv der tages slet ikke højde for rigtigheden af ​​eksisterende data - men forgæves! Det vil sige, at optagelsen er omskrevet, selvom den indeholdt præcis det, der var ønsket – men hvorfor? Lad os ordne det:

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

Mange mennesker er ikke klar over eksistensen af ​​sådan en vidunderlig operatør, så her er et snydeark IS DISTINCT FROM og andre logiske operatorer til at hjælpe:
PostgreSQL Antipatterns: kæmper mod horder af "døde"
…og lidt om operationer på kompleks ROW()-udtryk:
PostgreSQL Antipatterns: kæmper mod horder af "døde"

#3: Jeg genkender min kæreste ved at... blokere

bliver lanceret to identiske parallelle processer, som hver forsøger at markere posten som "i gang":

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

Selvom disse processer gør ting, der er uafhængige af hinanden, men inden for samme ID, vil den anden klient blive "låst" på denne anmodning, indtil den første transaktion er gennemført.

Løsning #1: opgaven er reduceret til den forrige

Lad os bare tilføje det igen IS DISTINCT FROM:

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

I denne form vil den anden anmodning simpelthen ikke ændre noget i databasen, alt er allerede "som det skal være" der - derfor vil der ikke forekomme nogen blokering. Dernæst behandler vi kendsgerningen om "ikke-finding" af posten i applikationsalgoritmen.

Løsning #2: rådgivende låse

Dette er et stort emne for en separat artikel, hvor du kan læse om det. anvendelsesmetoder og "faldgruber" ved rådgivende blokering.

Løsning #3: dumme opkald

Men det er præcis, hvad der skal ske for dig. samtidig arbejde med samme rekord? Eller har du for eksempel skruet op for algoritmerne til at kalde forretningslogik fra klientsiden? Men hvis du tænker over det?..

Kilde: www.habr.com