PostgreSQL Antipatterns: luftojmë me hordhitë e 'të vdekurve'.

Veçoritë e funksionimit të mekanizmave të brendshëm të PostgreSQL e lejojnë atë të jetë shumë i shpejtë në disa situata dhe "nuk shumë" në të tjera. Sot do të ndalemi në një shembull klasik të konfliktit midis asaj se si funksionon SGBD dhe asaj që bën zhvilluesi me të — UPDATE vs parimet MVCC.

Përmbledhje e ngjarjes nga një artikull të shkëlqyer:

Kur një rresht ndryshohet nga komanda UPDATE, në fakt kryhen dy operacione: DELETE dhe INSERT. Në versionin aktual të rreshtit vendoset xmax, e barabartë me numrin e transaksionit që ka kryer UPDATE. Pastaj krijohet versioni i ri i njëjtit rresht; vlera xmin e tij përputhet me vlerën xmax të versionit të mëparshëm.

Pas një kohe të caktuar pas përfundimit të kësaj transaksioni, versioni i vjetër ose i ri, në varësi të COMMIT/ROLLBACK, do të njihen si "të vdekur" (dead tuples) kur kaloni VACUUM në tabelë dhe do të pastrohen.

PostgreSQL Antipatterns: luftojmë me hordhitë e 'të vdekurve'.

Por kjo nuk do të ndodhë menjëherë, por problemet me "të vdekurit" mund të lindin shumë shpejt — gjatë një përditësimi të shumtë ose masiv të regjistrimeve në një tabelë të madhe, dhe pak më vonë përballeni me situatën që edhe VACUUM nuk mund të ndihmojë..

#1: I Like To Move It

Supozoni se metoda juaj në logjikën e biznesit funksionon siç duhet, dhe papritmas kupton se duhet të përditësojë fushën X në një regjistrim të caktuar:

UPDATE tbl SET X =  WHERE pk = $1;

Pastaj, gjatë ekzekutimit, zbulohet se fusha Y gjithashtu duhet të përditësohet:

UPDATE tbl SET Y =  WHERE pk = $1;

… dhe pastaj edhe Z — përse të bëjmë gjithçka në little?

UPDATE tbl SET Z =  WHERE pk = $1;

Sa versione të këtij regjistrimi kemi tani në bazë? Aha, 4 gjëra! Nga ato, një është aktuale, dhe 3 duhet të pastronin pas jush [auto]VACUUM.

Mos e bëni kështu! Përdorni përditësimin e të gjitha fushave me një kërkesë — pothuajse gjithmonë logjika e punës së metodës mund të ndryshohet në këtë mënyrë:

UPDATE tbl SET X = , Y = , Z =  WHERE pk = $1;

#2: Use IS DISTINCT FROM, Luke!

Pra, megjithatë keni dashur të përditësoni shumë shumë regjistrime në tabelë (në procesin e aplikimit të skriptit ose konvertuesit, për shembull). Dhe në skript fluturon diçka e tillë:

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

Dikushherë një kërkesë e tillë ndodhet mjaft shpesh dhe pothuajse gjithmonë jo për të mbushur një fushë të re të zbrazët, por për të korigjuar ndonjë gabim në të dhëna. Ndërkohë vetë saktësia e të dhënave që tashmë ekzistojnë nuk merret parasysh — dhe gabim! Pra, regjistrimi ripërpunohet, edhe nëse aty kishte saktësisht atë që duhej — dhe përse? Le të rregullojmë:

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

Shumë njerëz nuk e dinë për ekzistencën e një operatori të tillë të shkëlqyer, prandaj ja një përmbledhje për IS DISTINCT FROM dhe operatorët e tjerë logjikë në ndihmë:
PostgreSQL Antipatterns: luftojmë me hordhitë e 'të vdekurve'.
… dhe pak për operacionet mbi shprehjet komplekse: ROW()-shprehjet:
PostgreSQL Antipatterns: luftojmë me hordhitë e 'të vdekurve'.

#3: А я милого узнаю по… блокировке

Aktivizohen dy procese paralele të njëjta, secili prej të cilëve përpiqet të regjistrojë që regjistrimi është "në punë":

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

Edhe nëse këto procese bëjnë gjëra të pavarura nga njëra-tjetra, por brenda një ID, në këtë kërkesë klienti i dytë "do të bllokohet" derisa të përfundojë transaksioni i parë.

Zgjidhja №1: problemi i reduktuar në të kaluarën

Thjesht do të shtojmë përsëri IS DISTINCT FROM:

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

Në këtë formë, kërkesa e dytë thjesht nuk do të ndryshojë asgjë në bazë, pasi aty "është gjithçka siç duhet" — prandaj bllokimi nuk do të ndodhë. Më pas, fakti i "mosgjetjes" së regjistrimit tashmë do të trajtohet në algoritmin aplikativ.

Zgjidhja №2: bllokimet e këshillimit

Një temë e madhe për një artikull të veçantë, ku mund të lexoni për metodat e përdorimit dhe "gropat" e bllokimeve rekomanduese.

Zgjidhja №3: thirrje të pa[detyrueshme]

Në fakt, me siguri duhet të ndodhë punë e njëkohshme me të njëjtin regjistrim? Или вы все-таки накосячили с алгоритмами вызовов бизнес-логики со стороны клиента, например? А если подумать?..

Burimi: habr.com

Bleni hostim të besueshëm për faqe me mbrojtje nga DDoS, serverë VPS VDS 🔥 Bleni hostim të besueshëm për faqe me mbrojtje nga DDoS, serverë VPS VDS | ProHoster