Mga Antipattern sa PostgreSQL: nakig-away sa mga panon sa "patay"

Ang mga peculiarities sa internal nga mga mekanismo sa PostgreSQL nagtugot niini nga paspas kaayo sa pipila ka mga sitwasyon ug "dili kaayo paspas" sa uban. Karon atong ipunting ang usa ka klasiko nga pananglitan sa usa ka panagsumpaki tali sa kung giunsa ang usa ka DBMS molihok ug kung unsa ang gibuhat sa developer niini - UPDATE kumpara sa mga prinsipyo sa MVCC.

Mubo nga istorya gikan sa maayo nga artikulo:

Kung ang usa ka laray giusab pinaagi sa usa ka UPDATE nga sugo, duha ka mga operasyon ang aktuwal nga gihimo: DELETE ug INSERT. SA kasamtangan nga bersyon sa hilo Ang xmax gitakda nga katumbas sa gidaghanon sa transaksyon nga nagpahigayon sa UPDATE. Unya kini gibuhat usa ka bag-ong bersyon parehas nga linya; ang xmin nga kantidad niini nahiuyon sa xmax nga kantidad sa miaging bersyon.

Pipila ka panahon human kini nga transaksyon makompleto, ang daan o bag-ong bersyon, depende sa COMMIT/ROOLBACK, ilhon "patay" (patay nga tuples) sa paglabay VACUUM sumala sa lamesa ug gilimpyohan.

Mga Antipattern sa PostgreSQL: nakig-away sa mga panon sa "patay"

Apan dili kini mahitabo diha-diha dayon, apan ang mga problema sa "patay" dali nga makuha - sa gibalikbalik o mass update sa mga rekord sa usa ka dako nga lamesa, ug sa usa ka gamay sa ulahi ikaw makasugat sa sama nga sitwasyon Ang VACUUM dili makatabang.

#1: Ganahan Ko nga Ibalhin Kini

Ingnon ta nga ang imong pamaagi nagtrabaho sa lohika sa negosyo, ug sa kalit kini nahibal-an nga kinahanglan nga i-update ang X field sa pipila ka rekord:

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

Pagkahuman, samtang nagpadayon ang pagpatuman, nahimo nga ang uma sa Y kinahanglan usab nga i-update:

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

... ug unya usab Z - nganong mag-usik ug oras sa mga butang nga walay hinungdan?

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

Pila ka bersyon sa kini nga rekord ang naa sa database? Oo, 4 ka piraso! Niini, usa ang may kalabutan, ug ang 3 kinahanglan nga limpyohan pagkahuman nimo pinaagi sa [awtomatikong] VACUUM.

Ayaw pagbuhat niini nga paagi! Paggamit pag-update sa tanang field sa usa ka hangyo β€” halos kanunay ang lohika sa pamaagi mahimong mausab sama niini:

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

#2: Ang Paggamit LABING LAIN, Luke!

Busa, gusto pa nimo pag-update sa daghan, daghang mga rekord sa usa ka lamesa (sa panahon sa paggamit sa usa ka script o converter, pananglitan). Ug usa ka butang nga sama niini ang molupad sa script:

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

Ang usa ka hangyo sa gibana-bana nga kini nga porma mahitabo kanunay ug hapit kanunay dili aron pun-on ang usa ka walay sulod nga bag-ong field, apan aron matul-id ang pipila ka mga sayup sa datos. Sa samang higayon, siya mismo ang pagkahusto sa kasamtangan nga datos wala gikonsiderar sa tanan - apan sa kawang! Sa ato pa, ang rekord gisulat pag-usab, bisan kung kini adunay eksakto kung unsa ang gusto - apan ngano? Ayuhon nato:

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

Daghang mga tawo ang wala nahibal-an sa paglungtad sa ingon usa ka talagsaon nga operator, mao nga ania ang usa ka cheat sheet sa IS DISTINCT FROM ug uban pang lohikal nga mga operator aron makatabang:
Mga Antipattern sa PostgreSQL: nakig-away sa mga panon sa "patay"
... ug gamay bahin sa mga operasyon sa complex ROW()- mga ekspresyon:
Mga Antipattern sa PostgreSQL: nakig-away sa mga panon sa "patay"

#3: Nakaila ko sa akong hinigugma pinaagi sa... blocking

gilusad duha ka managsama nga parallel nga proseso, nga ang matag usa mosulay sa pagmarka sa entry nga kini "nag-uswag":

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

Bisan kung kini nga mga proseso sa tinuud naghimo sa mga butang nga independente sa usag usa, apan sa sulod sa parehas nga ID, ang ikaduha nga kliyente "ma-lock" sa kini nga hangyo hangtod mahuman ang una nga transaksyon.

Solusyon # 1: ang buluhaton gipakunhod ngadto sa nauna

Idugang na lang ta IS DISTINCT FROM:

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

Sa kini nga porma, ang ikaduha nga hangyo dili gyud magbag-o sa bisan unsang butang sa database, ang tanan naa na sa kinahanglan - busa, ang pag-block dili mahitabo. Sunod, giproseso namon ang kamatuoran nga "wala makit-an" ang rekord sa gipadapat nga algorithm.

Solusyon # 2: advisory lock

Usa ka dako nga hilisgutan alang sa usa ka lahi nga artikulo, diin mahimo nimong mabasa ang bahin mga pamaagi sa aplikasyon ug "rake" sa pag-block sa rekomendasyon.

Solusyon # 3: mga hungog nga tawag

Apan mao gyud kini ang angay mahitabo kanimo dungan nga trabaho nga adunay parehas nga rekord? O nagsamok ka ba sa mga algorithm sa pagtawag sa lohika sa negosyo sa bahin sa kliyente, pananglitan? Ug kung imong hunahunaon kini? ..

Source: www.habr.com

Idugang sa usa ka comment