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

De særlige kendetegn ved de interne mekanismer i PostgreSQL gør det muligt at være meget hurtig i nogle situationer og "ikke særlig hurtig" i andre. I dag vil vi fokusere på et klassisk eksempel på en konflikt mellem, hvordan et DBMS fungerer, og hvad udvikleren gør med det - OPDATERING vs MVCC principper.

Kort historie 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 strengen xmax er sat lig med nummeret på den transaktion, der udførte OPDATERING. Så er det skabt en ny version samme linje; dens xmin-værdi falder sammen med 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 vil du støde på samme situation VACUUM vil ikke være i stand til at hjælpe.

#1: Jeg kan godt lide at flytte den

Lad os sige, at din metode arbejder på forretningslogik, og pludselig indser den, at det ville være nødvendigt at opdatere X-feltet i en eller anden post:

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

Så, efterhånden som eksekveringen skrider frem, viser det sig, at Y-feltet også skal opdateres:

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

... og så også Z - hvorfor spilde tiden på 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 en relevant, og 3 skal ryddes op efter dig med [auto]VACUUM.

Gør det ikke på denne måde! Brug opdatering af 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å du ville stadig 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 forekommer ret ofte og næsten altid om 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 pladen er omskrevet, selvom den indeholdt præcis det ønskede – 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 på 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, at den er "i gang":

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

Selvom disse processer faktisk gør tingene uafhængigt 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 - derfor vil blokering ikke forekomme. Dernæst behandler vi det faktum at "ikke at finde" posten i den anvendte algoritme.

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

Et stort emne for en separat artikel, som du kan læse om påføringsmetoder og "rake" af anbefalet blokering.

Løsning #3: dumme opkald

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

Kilde: www.habr.com

Tilføj en kommentar