Cara mekanisme dalaman PostgreSQL berfungsi membolehkannya menjadi sangat pantas dalam sesetengah situasi dan tidak begitu pantas dalam situasi lain. Hari ini, kita akan melihat contoh klasik konflik antara cara DBMS berfungsi dan perkara yang dilakukan oleh pembangun dengannya: KEMASKINI lwn prinsip MVCC.
Plot ringkas daripada :
Apabila baris diubah suai oleh perintah KEMASKINI, dua operasi sebenarnya dilakukan: DELETE dan INSERT. versi semasa baris xmax ditetapkan kepada nombor transaksi yang melakukan KEMASKINI. Kemudian ia dicipta versi baru baris yang sama; nilai xminnya sepadan dengan nilai xmax versi sebelumnya.
Beberapa ketika selepas transaksi ini selesai, versi lama atau baharu, bergantung pada COMMIT/ROOLBACK, akan diiktiraf tupel mati apabila berlalu VACUUM mengikut jadual dan dibersihkan.

Tetapi ini tidak akan berlaku serta-merta, tetapi masalah dengan "mati" boleh diperolehi dengan cepat - dengan berulang atau dalam meja besar, dan sedikit kemudian menghadapi situasi yang .
#1: Saya Suka Memindahkannya
Katakan kaedah logik perniagaan anda sedang berjalan dan tiba-tiba menyedari bahawa ia perlu mengemas kini medan X dalam beberapa rekod:
UPDATE tbl SET X = <newX> WHERE pk = $1;Kemudian, apabila pelaksanaan berlangsung, ia mendapati bahawa medan Y juga perlu dikemas kini:
UPDATE tbl SET Y = <newY> WHERE pk = $1;…dan kemudian ada juga Z – kenapa perlu bersusah payah dengan perkara kecil?
UPDATE tbl SET Z = <newZ> WHERE pk = $1;Berapa banyak versi entri ini yang kini ada dalam pangkalan data? Ya, empat! Satu daripadanya adalah terkini dan tiga perlu dibersihkan dengan [auto]VACUUM.
Jangan buat begitu! Gunakannya! mengemas kini semua medan dalam satu permintaan — hampir selalu logik kaedah boleh diubah seperti ini:
UPDATE tbl SET X = <newX>, Y = <newY>, Z = <newZ> WHERE pk = $1;#2: Penggunaan ADALAH BERBEZA DARI, Luke!
Jadi, anda masih mahu (semasa menggunakan skrip atau penukar, sebagai contoh). Dan sesuatu seperti ini dimasukkan ke dalam skrip:
UPDATE tbl SET X = <newX> WHERE pk BETWEEN $1 AND $2;Permintaan lebih kurang borang ini ditemui agak kerap dan hampir selalu bukan untuk mengisi medan kosong baharu, tetapi untuk membetulkan beberapa ralat dalam data. ketepatan data sedia ada tidak diambil kira sama sekali - tetapi sia-sia! Iaitu, entri itu ditulis semula, walaupun ia mengandungi apa yang saya mahukan-tetapi mengapa perlu bersusah payah? Mari kita betulkan:
UPDATE tbl SET X = <newX> WHERE pk BETWEEN $1 AND $2 AND X IS DISTINCT FROM <newX>; Ramai orang tidak menyedari kewujudan pengendali yang begitu hebat, jadi berikut adalah helaian tipu IS DISTINCT FROM dan pengendali logik lain untuk membantu:

…dan sedikit tentang operasi di kompleks ROW()-ungkapan:

#3: Saya mengenali sayang saya dengan... menyekat
sedang dilancarkan dua proses selari yang sama, setiap satunya cuba menandakan rakaman sebagai "sedang berjalan":
UPDATE tbl SET processing = TRUE WHERE pk = $1;Walaupun proses ini melaksanakan tugas bebas, tetapi dalam ID yang sama, pelanggan kedua akan "dikunci" atas permintaan ini sehingga transaksi pertama selesai.
Penyelesaian #1: tugas dikurangkan kepada yang sebelumnya
Mari tambah lagi IS DISTINCT FROM:
UPDATE tbl SET processing = TRUE WHERE pk = $1 AND processing IS DISTINCT FROM TRUE;Dalam borang ini, pertanyaan kedua tidak akan mengubah apa-apa dalam pangkalan data; semuanya sudah "seperti yang sepatutnya"—jadi tiada sekatan akan berlaku. Fakta bahawa rekod "tidak dijumpai" kemudiannya dikendalikan dalam algoritma aplikasi.
Penyelesaian #2: kunci nasihat
Ini adalah topik besar untuk artikel berasingan, di mana anda boleh membaca tentangnya. .
Penyelesaian #3: panggilan bodoh
Tetapi inilah yang sepatutnya berlaku kepada anda. kerja serentak dengan rekod yang samaAtau mungkin anda mengacaukan algoritma panggilan logik perniagaan pihak pelanggan, sebagai contoh? Tapi kalau difikirkan balik...
Sumber: www.habr.com
