Modül dersleri (3/4)
Kilitleme ve GÜNCELLEME İÇİN SEÇ
Bir veritabanının tek bir terminalde yalıtılmış olarak nasıl çalıştığını anlamak basittir... hayır durun, bunu zaten söyledim!
Bazen "Atomik Güncellemeler" (ör. stock = stock - 1) yeterli değildir.
Kullanıcının 50€ değerinde ürün almaya yetecek bakiyeye sahip olup olmadığını kontrol etmeniz gerektiğini düşünelim:
SELECT balance FROM users WHERE id = 1;- JS: Bakiye 50'nin altındaysa engelleyin!
- Aksi takdirde ödeme işlemine devam edin...
- Kesintiyi çalıştırın! (Ve burada, 2. adımda kontrolü doğrularken, hesabını yakıp kül eden başka bir paralel çeki ateşleyen bir kullanıcı bulacaksınız ve şimdi sıfırın altına iniyorsunuz!).
GÜNCELLEME İÇİN Açık Kilitleme
Bir SELECT sonuna FOR UPDATE eklemek, masum okumanızı sihirli bir şekilde bir sonraki COMMIT'e kadar diğer istemcilere karşı mühürlü bir Kilit'e dönüştürür. Siz onlarla ne yapacağınıza karar verene kadar, hiç kimse bu belirli seçilen satırlarda UPDATE (veya eşzamanlı güncelleme için okuma) işlemi yapamayacak!
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;Hatta diğer okuyucuların durum okumalarını engellemeden (temel kilitteyse) okumaya devam etmesine olanak tanıyan, ancak siz taahhütte bulunana kadar sonraki olası güncellemeleri engelleyen FOR SHARE bile var. Değişiklikler için her zaman özel kilitleme maddesinin kaba kuvvetini kullanın:
Kendin dene
Normal zaman kapsamlı bir işlem açın ve ürün kimliği=5'in okunmasını özel olarak kilitleyin.\nİki adımlı bir sorgu çalıştırın:\n1. İşlemi açın (BEGIN)\n2. 'GÜNCELLEME İÇİN' seçeneğini ekleyerek, hiç kimsenin değiştirmeyeceğini garanti ederek ID 5 için tam satırı getiren 'ürünleri' sorgulayın.
İpucu göster
BEGIN;, yeni satır, GÜNCELLEME İÇİN SELECT * ÜRÜNLERDEN NEREDE id = 5;
3 denemeden sonra çözüm mevcut
Bazen işlem çok tehlikeli süreler boyunca askıda kalır (Çıkmazlık veya sonsuz beklemeler).\nBunu önlemek için veritabanına, satırın hemen kullanılabilir olmadığı andan itibaren vazgeçmesi komutunu verebilirsiniz: sonunda NOWAIT kullanarak, bu, bir SQL sunucusu istisnasının JS'ye geri dönmesine ve sonsuza kadar beklemeden yakalanmasına neden olur.\nKategori ID=1 için bir SELECT çalıştırın ve FOR UPDATE kullanın ancak NOWAIT'i zorunlu kılın.
İpucu göster
GÜNCELLEME ŞİMDİ BEKLEYİN İÇİN id = 1 NEREDE Kategorilerden * SEÇİN;
3 denemeden sonra çözüm mevcut