İş parçacığı için güvenli bir şekilde bir değeri (sayacı) sorgulamak ve artırmak nasıl? (yarış koşullarından kaçının)


10

Her satır bir sayaç (sadece bir tamsayı değeri) olan bir tabloda, geçerli değeri almak ve aynı zamanda artırmak gerekir .

Etkili, bunu yapmak istiyorum:

SELECT counter FROM table WHERE id=123
UPDATE table SET counter=counter+1 WHERE id=123

Ancak bunu iki sorgu olarak yapmak elbette iş parçacığı için güvenli değildir: aynı şeyi (aynı satırda) yapan birden çok işlem aynı sayaç değerini alabilir. Hepsinin benzersiz olmasını istiyorum, bu yüzden her işlem gerçek akım değerini alacak ve bir artıracaktı.

Satır başına manuel kilit uyguladığım bir yapı düşünebilirim, ancak bunu yapmanın daha kolay bir yolu olup olmadığını merak ediyorum?


belki de işlemler?
ypercubeᵀᴹ

Yanıtlar:


15

Güncelleme ifadeleri daha önce seçilmeden mükemmel çalışır! Tek ifadeler tanım gereği güvenli olduğundan, aynı anda gerçekleştirilen iki UPDATE sorgusu bile satırın iki kez artmasına neden olur.

Aslında PHP betiğinizin değerini seçmek istiyorsanız, onunla bir şeyler yapın ve daha sonra bu tam sayaç değerini güncellemek istiyorsanız, aşağıdakileri yapabilirsiniz:

BEGIN;
SELECT `counter` FROM `table` WHERE `id` = 123 FOR UPDATE;
UPDATE `table` SET `counter` = `counter`+1 WHERE `id` = 123;
COMMIT;

Bu yeni bir işlem başlatır, ardından güncellemek istediğiniz satırları seçer ve yalnızca kilitler. Daha sonra, diğer istemcilerin içeriklerini değiştirmesi veya hatta kilitli satırlara erişmesi konusunda endişelenmeden bunları güvenle güncelleyebilirsiniz. Son olarak değişikliklerinizi yapmalısınız.

Ayrıca izolasyon seviyeleri hakkında bir şeyler okumalısınız . Büyük olasılıkla READ UNCOMMITTEDyalıtım düzeyi gibi bir değer istemezsiniz . Bu kullanım durumu için her şey yolunda olmalı.


Başka yerlerde UPDATE table SET counter = counter + 1yeterince atomik olduğunu okudum ? Hala onu çevreleyen işlem bildirimlerine mi ihtiyacınız var?
CMCDragonkai

@CMCDragonkai Sorgunuz tek başına atomik, ancak FOR UPDATEönceki değeri seçtiyseniz ve kullanmadıysanız ve işlemler gerçekleştirdiğinizde, seçtiğiniz değer güncelleme sorgusunda kullanılan değerden farklı olabilir. Sorgu kombinasyonum, değer seçilir seçilmez satırı kilitler ve bu nedenle bu tam sayaç değerinin güncelleştirme sorgusunda kullanılmasını sağlar.
GhostGambler

Tamam, ama bu sadece artırım dışında bir iş yapmam gerekiyorsa değil mi? Durduğu gibi, tek bir atomik güncelleme sorgusu yapmak istediğim tek şey yeterince iyi?
CMCDragonkai

1
@CMCDragonkai Sütuna dokunan başka bir sorgu yürütmezseniz, iyisinizdir.
GhostGambler
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.