Antipattern PostgreSQL: nglawan gerombolan "mati"

Keanehan mekanisme internal PostgreSQL ngidini supaya cepet banget ing sawetara kahanan lan "ora cepet banget" ing liyane. Dina iki kita bakal fokus ing conto klasik konflik antarane cara kerja DBMS lan apa sing ditindakake pangembang - UPDATE vs prinsip MVCC.

Crita ringkes saka artikel gedhe:

Nalika baris diowahi kanthi printah UPDATE, rong operasi sing bener ditindakake: DELETE lan INSERT. ING versi string saiki xmax disetel padha karo jumlah transaksi sing nindakake UPDATE. Banjur digawe versi anyar baris padha; nilai xmin sawijining pas karo nilai xmax saka versi sadurungΓ©.

Sawetara wektu sawise transaksi iki rampung, versi lawas utawa anyar, gumantung ing COMMIT/ROOLBACK, bakal diakoni "mati" (tuples mati) nalika liwat VACUUM miturut meja lan diresiki.

Antipattern PostgreSQL: nglawan gerombolan "mati"

Nanging iki ora bakal kedadeyan langsung, nanging masalah karo "mati" bisa dipikolehi kanthi cepet - kanthi bola-bali utawa nganyari massa cathetan ing meja gedhe, lan sethitik mengko sampeyan bakal nemokke kahanan sing padha VACUUM ora bakal bisa nulungi.

#1: Aku Seneng Ngalih

Ngomongake cara sampeyan nggarap logika bisnis, lan dumadakan ngerti yen perlu nganyari lapangan X ing sawetara rekaman:

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

Banjur, nalika eksekusi maju, ternyata lapangan Y uga kudu dianyari:

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

... banjur uga Z - kok sampah wektu ing trifles?

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

Pira versi rekaman iki sing saiki ana ing basis data? wis, 4 biji! Saka jumlah kasebut, siji cocog, lan 3 kudu diresiki sawise sampeyan kanthi [otomatis] VACUUM.

Aja kaya ngono! Gunakake nganyari kabeh lapangan ing siji panjalukan - meh tansah logika cara bisa diganti kaya iki:

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

# 2: Gunakake IS BEDA, Lukas!

Dadi, sampeyan isih pengin nganyari akeh, akeh cathetan ing meja (sajrone nggunakake script utawa konverter, contone). Lan kaya iki mabur menyang skrip:

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

A request ing kira-kira wangun iki kedaden cukup asring lan meh ora kanggo ngisi kolom anyar kosong, nanging kanggo mbenerake sawetara kasalahan ing data. Ing wektu sing padha, dheweke dhewe bener data sing wis ana ora dijupuk menyang akun ing kabeh - nanging muspra! Tegese, rekaman kasebut ditulis maneh, sanajan isine persis apa sing dikarepake - nanging kenapa? Ayo didandani:

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

Akeh wong sing ora ngerti anane operator sing apik banget iki, mula ana cheat sheet IS DISTINCT FROM lan operator logis liyane kanggo mbantu:
Antipattern PostgreSQL: nglawan gerombolan "mati"
... lan sethitik babagan operasi ing Komplek ROW()-ekspresi:
Antipattern PostgreSQL: nglawan gerombolan "mati"

#3: Aku kenal karo kekasihku kanthi ... ngalangi

lagi diluncurake loro proses podo identik, sing saben-saben nyoba kanggo menehi tandha entri sing "ing proses":

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

Sanajan proses kasebut bener-bener nindakake samubarang kanthi mandiri, nanging ing ID sing padha, klien kapindho bakal "dikunci" ing panyuwunan iki nganti transaksi pisanan rampung.

Solusi #1: tugas wis suda kanggo sadurunge

Ayo ditambahake maneh IS DISTINCT FROM:

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

Ing wangun iki, panjalukan kapindho mung ora bakal ngganti apa wae ing database, kabeh wis kaya sing dikarepake - mula, pamblokiran ora bakal kedadeyan. Sabanjure, kita ngolah kasunyatan "ora nemokake" rekaman ing algoritma sing ditrapake.

Solusi #2: kunci pitutur

Topik gedhe kanggo artikel sing kapisah, sing bisa diwaca cara aplikasi lan "rake" pamblokiran rekomendasi.

Solusi #3: telpon bodho

Nanging iki persis apa sing kudu kelakon kanggo sampeyan karya simultaneous karo rekaman padha? Utawa apa sampeyan kekacoan karo algoritma kanggo nelpon logika bisnis ing sisih klien, contone? Lan yen sampeyan mikir babagan iki? ..

Source: www.habr.com

Add a comment