Lompati ke konten utama
Modul 11 · Pelajaran 3 dari 443/57 dalam kursus~15 min
Pelajaran modul (3/4)

Mengunci dan PILIH UNTUK UPDATE

Memahami cara kerja database secara terpisah pada satu terminal itu sederhana... tidak tunggu, saya sudah mengatakannya! Terkadang "Pembaruan Atom" (misalnya stock = stock - 1) saja tidak cukup.

Bayangkan Anda harus memeriksa apakah pengguna memiliki cukup saldo untuk membeli barang senilai 50€:

1.SELECT balance FROM users WHERE id = 1; 2. JS: Jika saldo < 50, blokir! 3. Jika tidak, lanjutkan dengan checkout... 4. Jalankan pemotongannya! (Dan di sini Anda menemukan pengguna yang, saat memvalidasi pemeriksaan pada langkah 2, melepaskan pemeriksaan paralel lain yang membakar akun mereka dan sekarang Anda berada di bawah nol!).

UNTUK UPDATE Penguncian Eksplisit

Menambahkan FOR UPDATE di akhir SELECT secara ajaib mengubah pembacaan tidak bersalah Anda menjadi Kunci tersegel terhadap klien lain hingga COMMIT berikutnya. Tidak ada orang lain yang dapat melakukan UPDATE (atau pembacaan-untuk-pembaruan secara bersamaan) pada baris tertentu yang dipilih tersebut sampai Anda memutuskan apa yang harus dilakukan dengannya!

SQL
BEGIN;

-- If id=3 had already been locked by T1, T2 will sit in perpetual loading on this "read"
-- frozen in place, before receiving the raw data, until T1 runs COMMIT freeing everyone!
SELECT balance
FROM users
WHERE id = 3
FOR UPDATE;

-- at this point our Node JS instance lives with the guarantee, knowing for certain that NO ONE ELSE in the world has
-- manipulated (nor been able to read with intent to alter) that balance while we complete the application logic

UPDATE users SET balance = balance - 50 WHERE id = 3;

COMMIT;

Bahkan ada FOR SHARE yang memungkinkan pembaca lain terus membaca (jika pada kunci dasar) tanpa memblokir pembacaan status, tetapi memblokir kemungkinan pembaruan berikutnya hingga Anda berkomitmen. Namun untuk modifikasi, selalu gunakan kekerasan dari klausa penguncian eksklusif:

Cobalah sendiri

Latihan#sql.m11.l3.e1
Upaya: 0Memuat…

Buka transaksi dengan cakupan waktu normal dan secara eksklusif mengunci pembacaan ID produk=5.\nJalankan kueri dua langkah:\n1. Buka transaksi (MULAI)\n2. Kueri 'produk' yang mengambil baris lengkap untuk ID 5 dengan jaminan tidak ada yang akan mengubahnya, dengan melampirkan opsi 'UNTUK PEMBARUAN'.

Memuat editor…
Tunjukkan petunjuk

BEGIN;, baris baru, SELECT * FROM produk WHERE id = 5 UNTUK UPDATE;

Solusi tersedia setelah 3 upaya

Latihan#sql.m11.l3.e2
Upaya: 0Memuat…

Terkadang transaksi terhenti selama periode bencana (Kebuntuan atau penantian tak terbatas).\nUntuk mencegah hal ini, Anda dapat memerintahkan database untuk berhenti saat baris tidak segera tersedia: menggunakan SEKARANG di akhir, yang akan menyebabkan pengecualian server SQL memantul kembali ke JS untuk dicoba ditangkap tanpa terhenti selamanya.\nJalankan SELECT untuk ID kategori=1 dan gunakan UNTUK UPDATE tetapi terapkan SEKARANG.

Memuat editor…
Tunjukkan petunjuk

PILIH * DARI kategori DIMANA id = 1 UNTUK UPDATE SEKARANG, TUNGGU;

Solusi tersedia setelah 3 upaya