7 dk

CRUD uygulamalarında yarış durumları: nedenleri ve pratik çözümler

CRUD uygulamalarındaki yarış durumları çift siparişlere ve yanlış toplamlara yol açabilir. Ortak çarpışma noktalarını ve kısıtlar, kilitler ve UI korumalarıyla pratik çözümleri öğrenin.

CRUD uygulamalarında yarış durumları: nedenleri ve pratik çözümler

CRUD uygulamasında bir yarış durumu nasıl görünür

Yarış durumu, iki (veya daha fazla) isteğin neredeyse aynı anda aynı veriyi güncellemesi ve nihai sonucun zamanlamaya bağlı olması durumunda oluşur. Her istek kendi başına doğru görünür. Birlikte yanlış bir sonuç üretirler.

Basit bir örnek: iki kişi aynı müşteri kaydında bir saniye içinde Kaydet'e basar. Biri e-postayı günceller, diğeri telefon numarasını. Eğer her iki istek de tam kaydı gönderiyorsa, ikinci yazma ilkini üzerine yazabilir ve bir değişiklik hata vermeden kaybolur.

Bunu hızlı uygulamalarda daha çok görürsünüz çünkü kullanıcılar dakikada daha fazla eylem tetikleyebilir. Ayrıca yoğun anlarda artar: flash sale'ler, ay sonu raporlaması, büyük bir e-posta kampanyası ya da aynı satırlara birikmiş isteklerin çarpması.

Kullanıcılar nadiren "yarış durumu" diye şikayet eder. Belirtileri bildirirler: çift siparişler veya yorumlar, kaybolan güncellemeler ("Kaydettim ama geri gitti"), garip toplamlar (stok negatif oldu, sayaçlar geriye sıçradı) veya beklenmedik şekilde değişen durumlar (onaylandı, sonra tekrar beklemede oldu).

Yeniden denemeler işi kötüleştirir. İnsanlar çift tıklar, yavaş bir yanıttan sonra sayfayı yeniler, iki sekmeden gönderir veya kararsız ağ nedeniyle tarayıcılar ve mobil uygulamalar isteği yeniden gönderebilir. Sunucu her isteği yeni bir yazma olarak ele alırsa iki create, iki ödeme ya da bir kez olması gereken iki durum değişikliği alabilirsiniz.

Yarış durumları neden düşündüğünüzden daha sık olur

Çoğu CRUD uygulaması basit görünür: bir satırı oku, bir alanı değiştir, kaydet. Sorun, uygulamanızın zamanlamayı kontrol etmemesidir. Veritabanı, ağ, yeniden denemeler, arka plan işleri ve kullanıcı davranışı hepsi üst üste biner.

Yaygın tetikleyicilerden biri iki kişinin aynı kaydı düzenlemesidir. İkisi de aynı "güncel" değerleri yükler, ikisi de geçerli değişiklikler yapar ve son kaydetme ilkini sessizce üzerine yazar. Kimse yanlış yapmadı ama bir güncelleme kayboldu.

Tek bir kişiyle de olabilir. Kaydet düğmesine çift tıklama, geri/ileri gezinme ya da yavaş bir bağlantı kişinin tekrar Gönder'e basmasına neden olabilir ve aynı yazma iki kez gönderilebilir. Uç nokta idempotent değilse çoğaltmalar, iki kez ücretlendirme veya bir durumun iki adım ilerlemesi görebilirsiniz.

Modern kullanım daha fazla üst üste binme getirir. Aynı hesaba girişli birden fazla sekme veya cihaz çakışan güncellemeler gönderebilir. E-postalar, faturalama, senkronizasyon, temizlik gibi arka plan işleri aynı satırlara dokunabilir. İstemci, yük dengeleme veya iş çalıştırıcıdaki otomatik yeniden denemeler zaten başarıyla gerçekleşen bir isteği tekrar edebilir.

Hızla özellik gönderiyorsanız, aynı kayıt herkesin hatırladığından daha fazla yerden güncellenir. Koder.ai gibi sohbet tabanlı bir üretici kullanıyorsanız uygulama daha da hızlı büyüyebilir; bu yüzden eşzamanlılığı bir kenar durumu değil normal davranış olarak ele almakta fayda var.

İzlemeniz gereken ortak çarpışma noktaları

Yarış durumları nadiren "kayıt oluşturma" demolarında çıkar. İki isteğin aynı gerçeğe neredeyse aynı anda dokunduğu yerlerde ortaya çıkarlar. Yaygın sıcak noktaları bilmek, yazmaları baştan güvenli tasarlamanıza yardımcı olur.

Sayaçlar ve "sonraki numara" alanları

"Sadece 1 ekle" gibi görünen her şey yük altında bozulabilir: beğeniler, görüntüleme sayıları, toplamlar, fatura numaraları, bilet numaraları. Riskli desen değeri oku, ekle, sonra geri yazmaktır. İki istek aynı başlangıç değerini okuyup birbirlerini üzerine yazabilir.

Durum geçişleri

Taslak -> Gönderildi -> Onaylandı -> Ödendi gibi iş akışları basit görünür, ama çarpışmalar yaygındır. Sorun, iki eylem aynı anda mümkün olduğunda başlar (onayla ve düzenle, iptal et ve öde gibi). Koruma olmazsa bir kayıt adımları atlayabilir, geri dönebilir veya farklı tablolarda farklı durumlar gösterebilir.

Durum değişikliklerini bir sözleşme gibi ele alın: yalnızca bir sonraki geçerli adıma izin verin ve diğerlerini reddedin.

Stok, kapasite ve rezervasyon slotları

Kalan koltuklar, stok sayıları, randevu slotları ve "kalan kapasite" alanları klasik aşırı satış sorununu yaratır. İki alıcı aynı anda ödeme yaparken her ikisi de müsaitlik görür ve her ikisi de başarılı olur. Eğer veritabanı son hakem değilse, sonunda sahip olduğunuzdan daha fazlasını satarsınız.

Tekillik ve "sadece bir tane aktif" kuralları

Bazı kurallar mutlak: hesap başına bir e-posta, kullanıcı başına bir aktif abonelik, kullanıcı başına bir açık sepet. Bunlar genellikle önce kontrol ettiğinizde başarısız olur ("var mı?") sonra insert yaparsınız. Eşzamanlılık altında her iki istek de kontrolü geçebilir.

CRUD akışlarını hızlı yazıyorsanız (örneğin Koder.ai ile sohbet ederek uygulama oluşturuyorsanız), bu sıcak noktaları erken not edin ve sadece UI kontrolleriyle değil, kısıtlar ve güvenli yazmalarla destekleyin.

UI'den gelen çift gönderimler ve tekrar eden istekler

Birçok yarış durumu sıkıcı bir şeyle başlar: aynı eylem iki kez gönderilir. Kullanıcılar çift tıklar. Ağ yavaş olduğunda tekrar tıklarlar. Bir telefon iki dokunuş kaydedebilir. Bazen kasıtlı bile değildir: bir POST'tan sonra sayfa yenilenir ve tarayıcı yeniden gönderme teklif eder.

Böyle olunca backend paralel iki create veya update çalıştırabilir. Her ikisi de başarılı olursa çoğaltmalar, yanlış toplamlar veya örneğin onay+onay gibi bir durum değişikliği iki kez çalışabilir. Rastgele görünür çünkü zamanlamaya bağlıdır.

En güvenli yaklaşım derinlemesine savunmadır. UI'yı düzeltin, ama UI'nın başarısız olacağını varsayın.

Çoğu yazma akışına uygulayabileceğiniz pratik değişiklikler:

  • İlk tıklamada gönderimi devre dışı bırakın ve belirgin bir "kaydediliyor" durumu gösterin.
  • Başarılı bir POST'tan sonra yeniden gönderme olmasın diye yönlendirme yapın.
  • İdempotentlik anahtarı kullanın: sunucunun sadece bir kez kabul ettiği, kullanıcı eylemine özgü benzersiz token.
  • İki aynı insert'in ikisinin de kazanamayacağı şekilde veritabanı tekillik kuralıyla destekleyin.

Örnek: bir kullanıcı mobilde "Faturayı Öde"ye iki kez basıyor. UI ikinci dokunuşu engellemeli. Sunucu da aynı idempotency key'i gördüğünde ikinci isteği reddetmeli ve ilk başarılı sonucu geri döndürmeli, iki kez ücretlendirme olmamalı.

Senkronizasyon dışına çıkan durum geçişleri

Durum alanları basit hissedilir ama iki şey aynı anda onları değiştirmeye çalıştığında karmaşıklaşır. Bir kullanıcı Onayla'ya basarken otomatik bir iş aynı kaydı Süresiz olarak işaretleyebilir ya da iki ekip üyesi aynı öğeyi farklı sekmelerde işler. Her iki güncelleme de başarılı olabilir, ama nihai durum kurallarınıza değil zamanlamaya bağlı olur.

Durumu küçük bir durum makinesi gibi ele alın. İzin verilen hareketlerin kısa bir tablosunu tutun (örneğin: Taslak -> Gönderildi -> Onaylandı ve Gönderildi -> Reddedildi). Sonra her yazma şunu kontrol etsin: "Bu geçiş mevcut durumdan izinli mi?" Değilse sessizce overwrite etmek yerine reddedin.

İyimser kilitleme, diğer kullanıcıları engellemeden eski güncellemeleri yakalamanıza yardımcı olur. Bir sürüm numarası (veya updated_at) ekleyin ve kaydederken bunun eşleşmesini zorunlu kılın. Eğer başka biri sizin yükledikten sonra satırı değiştirdiyse, güncellemeniz sıfır satırı etkiler ve net bir mesaj gösterebilirsiniz: "Bu öğe değişti, yenileyip tekrar deneyin."

Durum güncellemeleri için basit bir desen:

  • Geçerli durumu ve sürümü oku
  • Geçişi doğrula
  • Bir korunmayla güncelle (WHERE status = ? AND version = ?)
  • Sürümü arttır

Ayrıca durum değişikliklerini tek bir yerde tutun. Eğer güncellemeler ekranlara, arka plan işlerine ve webhook'lara yayılmışsa kuralı kaçırırsınız. Her seferinde aynı geçiş kontrollerini uygulayan tek bir fonksiyon veya endpoint arkasına koyun.

Zaman içinde kayan sayaçlar ve toplamlar

Güvenle değişiklik yapın
Kenar durumlar çıkarsa geri alabilmek için kısıtları taşıyıp snapshots ve rollback kullanın.

En yaygın sayaç hatası zararsız görünür: uygulama bir değeri okur, 1 ekler, sonra geri yazar. Yük altında iki istek aynı sayıyı okuyabilir ve her ikisi de aynı yeni sayıyı yazar, böylece bir artış kaybolur. Bu, testte "genellikle çalıştığı" için kolayca gözden kaçırılır.

Oku sonra yaz yerine atomik güncellemeyi tercih edin

Bir değer sadece arttırılıyor veya azaltılıyorsa, veritabanının tek ifadede yapmasına izin verin. Böylece veritabanı birden çok istek aynı anda geldiğinde değişiklikleri güvenli şekilde uygular.

UPDATE posts
SET like_count = like_count + 1
WHERE id = $1;

Aynı fikir stok, görüntüleme sayıları, yeniden deneme sayaçları ve "yeni = eski + delta" şeklinde ifade edilebilen her şey için geçerlidir.

Toplamlar, hesaplanabilecek şeyi sakladığınızda sürüklenir

Toplamlar genellikle türetilmiş bir sayıyı (order_total, account_balance, project_hours) sakladığınızda yanlış olur ve birden fazla yerden güncellenir. Toplamı kaynak satırlardan (kalemler, defter girdileri) hesaplayabiliyorsanız birçok sürüklenme hatasından kaçınırsınız.

Hızı için toplam saklamanız gerekiyorsa, bunu kritik bir yazma gibi ele alın. Kaynak satırların güncellenmesini ve saklanan toplamı aynı işlemde tutun. Aynı toplamı aynı anda sadece bir yazarın güncelleyebildiğinden emin olun (kilitleme, korumalı güncellemeler veya tek bir sahip yolu). İmkansız değerleri engelleyen kısıtlar ekleyin (örneğin negatif stok). Sonra ara sıra toplamı yeniden hesaplayıp uyumsuzlukları işaretleyen bir arka plan uzlaşması çalıştırın.

Somut örnek: iki kullanıcı aynı sepete aynı anda ürün ekliyor. Her istek cart_total'ı okuyup kendi ürün fiyatını ekler ve geri yazarsa bir ekleme kaybolabilir. Eğer sepetteki kalemleri ve sepet toplamını tek bir işlemde güncellerseniz, yoğun paralel tıklarda bile toplam doğru kalır.

Önce veritabanı kısıtlarıyla çarpışmaları durdurun

Daha az yarış durumu istiyorsanız veritabanından başlayın. Uygulama kodu yeniden dener, zaman aşımına uğrar veya iki kez çalışır. Bir veritabanı kısıtı, iki istek aynı anda gelse bile doğru kalan son kapıdır.

Tekil kısıtlar, asla olmaması gereken çoğaltmaları durdurur: e-posta adresleri, sipariş numaraları, fatura kimlikleri veya "kullanıcı başına bir aktif abonelik" kuralı. İki kayıt aynı anda gelirse veritabanı bir satırı kabul eder diğerini reddeder.

Yabancı anahtarlar kırık referansları önler. Onlarsız, bir istek ana kaydı silerken başka bir istek o ana işaret eden bir alt kayıt oluşturabilir ve bu da sonra temizlemesi zor yetim satırlar bırakır.

Check kısıtları değerleri güvenli aralıkta tutar ve basit durum kurallarını uygular. Örneğin quantity >= 0, rating 1 ile 5 arasında veya status izin verilen bir küme ile sınırlı.

Kısıt hatalarını "sunucu hatası" gibi görmek yerine beklenen sonuçlar olarak ele alın. Tekil, yabancı anahtar ve check ihlallerini yakalayın, "Bu e-posta zaten kullanılıyor" gibi net bir mesaj döndürün ve ayrıntıları iç sızdırmadan loglayın.

Örnek: lag sırasında iki kişi "Sipariş Oluştur"a basarsa. (user_id, cart_id) üzerinde tekil bir kısıt varsa iki sipariş almazsınız. Bir sipariş ve bir temiz, açıklanabilir reddedilme alırsınız.

Bir değişikliğin kazanması gerektiğinde işlemler ve kilitler kullanın

Bazı yazmalar tek bir ifade değildir. Bir satırı okursunuz, bir kural kontrol edersiniz, bir durumu güncellersiniz ve belki bir denetim kaydı eklersiniz. İki istek bunu aynı anda yaparsa ikisi de kontrolü geçip yazabilir. Bu klasik başarısızlık desenidir.

Çok adımlı yazmayı tek bir veritabanı işleminde sarın ki tüm adımlar birlikte başarılı olsun ya da hiç olmasın. Daha da önemlisi, işlem aynı veriyi kimlerin aynı anda değiştirebileceğini kontrol etmenize olanak verir.

Sadece bir aktörün aynı anda bir kaydı düzenleyebildiği durumlarda satır düzeyinde kilit kullanın. Örneğin: sipariş satırını kilitleyin, hâlâ "beklemede" olup olmadığını doğrulayın, sonra "onaylandı"ya çevirin ve denetim girişini yazın. İkinci istek bekler, sonra durumu yeniden kontrol eder ve durur.

İyimser vs karamsar kilitleme

Çarpışmalar ne sıklıkta oluyor ona göre seçin:

  • İyimser kilitleme: bir sürüm numarası (veya updated_at) ekleyin ve sadece eşleşiyorsa güncelleyin.
  • Karamsar kilitleme: önce satırı kilitleyin, sonra aynı işlem içinde okuyup güncelleyin.

Kilidi kısa tutun. Kilidi tutarken mümkün olduğunca az iş yapın: dış API çağrıları, yavaş dosya işleri veya büyük döngüler yapmayın. Koder.ai gibi araçlarla akış oluşturuyorsanız, işlemi sadece veritabanı adımlarıyla sınırlayıp diğer işleri commit'ten sonra yapın.

Adım adım: bir yazma akışını uçtan uca sertleştirin

Eşzamanlılığı baştan planlayın
Kod üretmeden önce her durum değişikliğini ve idempotent yazmayı adım adım eşleyin.

Para veya güven kaybına yol açabilecek bir akışı seçin. Yaygın bir örnek: sipariş oluştur, stoğu ayır, sonra sipariş durumunu onaylandı olarak ayarla.

Kodunuzun bugün hangi adımları yaptığını sırayla yazın. Ne okundu, ne yazıldı ve "başarı" ne anlama geliyor açıkça belirtin. Çarpışmalar, okuma ile daha sonra yapılan yazma arasındaki boşlukta saklanır.

Çoğu yığın için işe yarayan sertleştirme yolu:

  • Engellemeniz gereken kötü sonuçları tanımlayın (örneğin: stokun negatif olması veya aynı sipariş satırı için iki rezervasyon).
  • Bu sonucu imkansız kılan bir veritabanı kuralı ekleyin (örneğin: stock < 0'ı engelleyen CHECK kısıtı ve rezervasyonlar için (order_id, sku) üzerinde UNIQUE kısıt).
  • Tüm akışı bir işlem içinde sarın ve sonucu belirleyen satırları kilitleyin (örneğin: stok satırını kilitleyip sonra stok çıkarın).
  • Mümkünse güncellemeyi tek ifadede yapın (örneğin: "update stock where stock >= qty" böylece güvenli şekilde başarısız olur).
  • Çakışmaları temizce yönetin: birkaç kez yeniden deneyin veya net bir "Stok tükendi, lütfen yenileyin" mesajı döndürün.

Düzelttiğinizi kanıtlayan bir test ekleyin. Aynı ürün ve miktar için iki isteği aynı anda çalıştırın. Tam olarak bir siparişin onaylandığını ve diğerinin kontrollü bir şekilde başarısız olduğunu doğrulayın (negatif stok yok, çift rezervasyon yok).

Koder.ai gibi hızla uygulama üreten platformlarla çalışıyorsanız bile, bu kontrol listesi en önemli yazma yollarında yapılmaya değer.

Yarış durumlarını canlı tutan yaygın hatalar

En büyük nedenlerden biri UI'ya güvenmektir. Devre dışı bırakılan düğmeler ve istemci tarafı kontroller yardımcı olur, ama kullanıcılar çift tıklayabilir, sayfayı yenileyebilir, iki sekme açabilir veya isteği kararsız bir bağlantıdan yeniden oynatabilir. Sunucu idempotent değilse çoğaltmalar içeri sızar.

Başka bir sessiz hata: bir veritabanı hatasını (örneğin tekil kısıt ihlali) yakalayıp yine de akışı devam ettirirsiniz. Bu çoğunlukla "oluşturma başarısız oldu ama yine de e-posta gönderildi" veya "ödeme başarısız oldu ama yine de sipariş ödendi olarak işaretlendi" gibi sonuçlara yol açar. Yan etkiler oluştuğunda geri almak zordur.

Uzun işlemler de tuzaktır. Email, ödeme veya üçüncü parti API çağrıları sırasında bir işlemi açık tutarsanız, kilitleri gereğinden fazla tutarsınız. Bu beklemeyi, zaman aşımını ve isteklerin birbirini engellemesini arttırır.

Arka plan işleri ile kullanıcı eylemlerini tek bir gerçek kaynağı olmadan karıştırmak split-brain durumları yaratır. Bir iş yeniden dener ve bir satırı güncellerken kullanıcı onu düzenliyorsa her iki taraf da kendini son yazan zanneder.

Gerçekten çözmeyen birkaç "çözüm":

  • Sadece UI tarafında çift gönderimi önlemek
  • Bir hatayı yutup sanki hiçbir şey olmamış gibi devam etmek
  • Ağ çağrılarını uzun bir işlem içinde yapmak
  • İşleri ve kullanıcı isteklerini aynı durumu farklı yollarla güncellemeye bırakmak
  • Sayaçları read-modify-write ile güncellemek yerine atomik güncellemeler kullanmamak

Koder.ai ile geliştiriyorsanız da aynı kurallar geçerlidir: daha iyi UI korumaları değil, sunucu tarafı kısıtları ve net işlem sınırları isteyin.

Yayına almadan önce hızlı kontroller

Durum dönüşümlerini düzeltin
Çakışan güncellemeler temizce başarısız olsun diye durum alanlarını açık geçişlere dönüştürün.

Yarış durumları genellikle gerçek trafik altında ortaya çıkar. Yayından önce yapılan bir geçiş en yaygın çarpışma noktalarını yeniden yazmadan yakalayabilir.

Veritabanından başla. Bir şey benzersiz olmak zorundaysa (e-postalar, fatura numaraları, kullanıcı başına bir aktif abonelik), bunu gerçek bir UNIQUE kısıtı yapın, uygulama düzeyinde "önce kontrol ediyoruz" kuralı değil. Sonra kodunuzun kısıt bazen başarısız olur diye beklediğinden ve temiz, güvenli bir cevap döndürdüğünden emin olun.

Sonra duruma bakın. Herhangi bir durum değişikliği (Taslak -> Gönderildi -> Onaylandı) izin verilen geçişler kümesine karşı doğrulanmalı. İki istek aynı kaydı hareket ettirmeye çalışırsa ikinci istek reddedilmeli veya no-op olmalı, arada kalmış bir durum yaratmamalı.

Pratik bir ön sürüm kontrol listesi:

  • Benzersiz olması gereken her kural için UNIQUE kısıtların var olduğunu doğrulayın, kompozit olanlar dahil.
  • Her yazma endpoint'inin yeniden denenebilir olduğunu doğrulayın (idempotency key'ler, istek ID'leri veya doğal idempotentlik).
  • Okuma sonra yazma yapıyorsanız çok adımlı yazmaları işlem içine alın.
  • Sadece bir değişiklik kazanmalıysa kilit kullanın (örneğin, bir sipariş için tek bir onay).
  • Çakışma sinyallerini loglayın (duplicate key hataları, serialization failures, lock timeout'lar) ve artışlara alarm kurun.

Koder.ai üzerinde akışlar oluşturuyorsanız, bunları kabul kriterleri olarak ele alın: üretilen uygulama sadece mutlu yolu geçmesin, yinelemeler ve eşzamanlılık altında güvenli şekilde başarısız olsun.

Örnek senaryo: çift onayı önlemek

İki personel aynı satın alma talebini açar. Her ikisi de birkaç saniye içinde Onayla'ya basar. Her iki istek de sunucuya gider.

Ne yanlış gidebileceği karmaşıktır: istek iki kez onaylanır, iki bildirim gider ve onaylarla ilgili toplamlar (bütçe kullanımı, günlük onay sayısı) 2 artabilir. Her iki güncelleme kendi başına geçerli ama çarpışırlar.

PostgreSQL tarzı bir veritabanıyla iyi çalışan bir düzeltme planı:

1) Çift onayı veritabanında imkansız kılın

Onayları ayrı bir tabloda saklayın ve request_id üzerinde UNIQUE kısıtı uygulayın. Böylece uygulama kodunda hata olsa bile ikinci insert başarısız olur.

2) Durum değişikliğini bir işlem içinde sarın

Onaylarken tüm geçişi tek bir işlemde yapın:

  • İstek satırını kilitleyin (veya WHERE status = 'pending' gibi bir şartla güncelleyin).
  • Hâlâ pending olduğunu doğrulayın.
  • Onay kaydını yazın.
  • İstek durumunu approved olarak güncelleyin.

İkinci personel gecikirse ya 0 satır güncellendiğini görür ya da bir UNIQUE kısıt hatası alır. Her iki durumda da sadece bir değişiklik kazanır.

3) Net UI geri bildirimi verin

Düzeltmeden sonra ilk personel Onaylandı görür ve normal onay mesajını alır. İkinci personel şu dostça mesajı görür: "Bu talep zaten başka biri tarafından onaylandı. Güncellemek için sayfayı yenileyin." Dönenme, tekrar bildirim yok, sessiz hata yok.

Koder.ai gibi platformlarda (Go backend + PostgreSQL) bir CRUD akışı üretiyorsanız, bu onay eylemine dair kontrolleri bir kez ekleyip diğer "tek kazanan" eylemler için yeniden kullanabilirsiniz.

Sonraki adımlar: yarış düzeltmelerini geliştirme rutininizin parçası yapın

Yarış durumları, tekrarlayan bir rutin olarak ele alındığında en kolay düzelir, tek seferlik bir hata avı gibi değil. En önemli birkaç yazma yoluna odaklanın ve onları diğer her şeyden önce sıkıcı ama doğru hale getirin.

Önce en çok çarpışma yapan noktaları adlandırın. Birçok CRUD uygulamasında aynı üçlü çıkar: sayaçlar (beğeniler, stok, bakiyeler), durum değişimleri (Taslak -> Gönderildi -> Onaylandı) ve çift gönderimler (çift tıklama, yeniden denemeler, yavaş ağlar).

Dayanıklı bir rutin:

  • Her akış için tek gerçek kuralı yazın (örneğin: bir sipariş sadece pending'den onaylanabilir ve sadece bir kez).
  • Önce veritabanı kısıtlarını ekleyin (UNIQUE, FOREIGN KEY, CHECK) ki veritabanı imkansız durumları reddetsin.
  • Sadece bir değişikliğin kazanması gereken yerlerde işlem kilitleri ekleyin.
  • Her kritik iş akışı için küçük bir eşzamanlılık testi ekleyin (iki onay, iki artış, iki form gönderimi).
  • Veritabanı çakıştığında UI'nin net bir mesaj gösterdiğinden emin olun.

Koder.ai üzerinde geliştiriyorsanız, Planning Mode her yazma akışını adımlar ve kurallar halinde haritalamak için pratiktir. Yeni kısıtlar veya kilit davranışları sunarken hızlı geri dönüş için snapshot ve rollback imkanları da faydalıdır.

Zamanla bu bir alışkanlık olur: her yeni yazma özelliği bir kısıt, bir işlem planı ve en az bir eşzamanlılık testi ile gelir. CRUD uygulamalarındaki yarış durumları böylece sürpriz olmaktan çıkar.

SSS

Bir CRUD uygulamasında yarış durumu nedir?

Yarış durumu, iki istek neredeyse aynı anda aynı veriyi değiştirdiğinde ve sonucu zamanlamanın belirlediği durumda ortaya çıkar. Geçerli bir kaydetme işlemi diğerinin üzerine yazabilir, yinelenen kayıt oluşturabilir veya bir durumu iki kez değiştirebilir.

Hangi CRUD özelliklerinde yarış durumu görülme olasılığı daha yüksektir?

İzlenme sayaçlarına, envantere, rezervasyon kontenjanlarına, durum alanlarına ve benzersiz olması gereken kurallara sahip kayıtlara dikkat edin. Bu alanlarda sıkça kullanılan önce oku, sonra yaz deseni, istekler çakıştığında bozulur.

Kullanıcıların bir formu iki kez göndermesini nasıl engellerim?

İlk tıklamadan sonra düğmeyi devre dışı bırakın, ancak sunucuyu da koruyun. Her işlem için tek bir idempotency anahtarı gönderin ve bunu saklayın. Böylece tekrarlanan istekler ikinci bir kayıt oluşturmak yerine ilk sonucu döndürür.

Sayaçları güvenli biçimde nasıl güncellerim?

SQL ifadesinde 1 eklemek gibi, değeri doğrudan değiştiren bir veritabanı güncellemesi kullanın. Sayacı uygulamaya okuyup orada değiştirerek geri yazmayın.

Durum değişikliklerinin çakışmasını nasıl önlerim?

Durum değişikliğini, geçerli durumu denetleyen ve yalnızca geçerli sonraki adımlara izin veren tek bir sunucu tarafı kuralın arkasına alın. Eski veya geçersiz geçişleri açık bir mesajla reddedin.

İyimser kilitleme nedir?

İyimser kilitleme, kayıtla birlikte bir sürüm veya zaman damgası saklar. Güncelleme yalnızca bu değer hâlâ eşleşiyorsa başarılı olur, böylece uygulama kullanıcıya kaydı önce başka birinin değiştirdiğini söyleyebilir.

Ne zaman veritabanı kilidi kullanmalıyım?

Bir isteğin, birden fazla kaydı değiştirmeden önce karar vermesi gerektiğinde satır kilidi içeren bir işlem kullanın. Örneğin stok ayırırken ve siparişi onaylarken. Kilitli işi kısa tutun ve işlem içinde harici API çağrılarından kaçının.

Yarış durumlarında veritabanı kısıtları neden önemlidir?

Hesap başına tek e-posta veya istek başına tek onay gibi kurallar için benzersizlik kısıtları ekleyin. Geçerli başvurular ve değerler için yabancı anahtarlar ve denetim kısıtları ekleyin. Böylece iki istek aynı anda gelse bile veritabanı imkânsız durumları reddeder.

Envanterin eksiye düşmesini nasıl önlerim?

Stok güncellemesini tek bir işlem içinde koşullu yapın, örneğin yalnızca yeterli stok kaldığında düşürün. Güncelleme hiçbir satırı etkilemezse, fazla satılmış bir siparişi onaylamak yerine alıcıya ürünün mevcut olmadığını söyleyin.

Bir yazma akışını yarış durumları açısından nasıl test ederim?

Aynı kayıt veya miktar üzerinde aynı anda iki istek çalıştırın, ardından sonucu kontrol edin. Gerektiğinde tek isteğin kazandığını, çakışmaların denetimli bir yanıt döndürdüğünü ve veritabanında yinelenen ya da geçersiz veri bulunmadığını test edin.

Related posts