SQL ve kilitleme stratejileri hakkında bir sorum var. Örnek olarak, web sitemdeki resimler için bir görüntüleme sayacım olduğunu varsayalım. Ben şu ifadeleri gerçekleştirmek için benzer bir sproc veya varsa: SQL atomik arttırma ve kilitleme stratejileri - bu güvenli midir?
START TRANSACTION;
UPDATE images SET counter=counter+1 WHERE image_id=some_parameter;
COMMIT;
belirli image_id için sayaç değerini '0' t0 zamanında sahip olduğunu varsayalım. Aynı seans sayacını s1 ve s2 güncelleyen iki seans, t0 ile eşzamanlı olarak başlıyorsa, bu iki seansın her ikisinin de '0' değerini okuduğunu, '1'e yükselteceğini ve her ikisinin de sayacı' 1'e güncellemeye çalışabilme şansı var mıdır? 'Yani, sayaç' 2 'yerine' 1 'değerini alacak?
s1: begin
s1: begin
s1: read counter for image_id=15, get 0, store in temp1
s2: read counter for image_id=15, get 0, store in temp2
s1: write counter for image_id=15 to (temp1+1), which is 1
s2: write counter for image_id=15 to (temp2+1), which is also 1
s1: commit, ok
s2: commit, ok
Sonuç: Yanlış değer '1' image_id = 15 için,
Benim sorulara 2. olmalıydı şunlardır:
- bu senaryonun mümkün mü?
- Böyle bir durumda, işlem yalıtımı düzeyi önemli midir?
- Böyle bir çakışmayı bir hata olarak algılayacak bir çakışma çözümleyicisi var mı?
- Sorunlardan kaçınmak için herhangi bir özel sözdizimini kullanabilir (Karşılaştırma ve Takas (CAS) veya açık kilitleme teknikleri gibi)?
Genel bir yanıtla ilgileniyorum, ancak MySql ve InnoDB'ye özel yanıtlarla ilgilenmiyorum, çünkü InnoDB'de dizileri uygulamak için bu tekniği kullanmaya çalıştığım için.
DÜZENLEME: Aşağıdaki senaryo da aynı davranışla sonuçlanabilir. Yalıtım seviyesinde READ_COMMITED ya da daha yüksek olduğumuzu varsayıyorum, bu yüzden s2 işlemin başlangıcından itibaren değeri almasına rağmen s1 zaten sayacı '1' yazdı.
s1: begin
s1: begin
s1: read counter for image_id=15, get 0, store in temp1
s1: write counter for image_id=15 to (temp1+1), which is 1
s2: read counter for image_id=15, get 0 (since another tx), store in temp2
s2: write counter for image_id=15 to (temp2+1), which is also 1
s1: commit, ok
s2: commit, ok
MySQL http://stackoverflow.com/questions/4358732/is-incrementing-a-field-in-mysql-atomic || MS http://stackoverflow.com/questions/193257/in-ms-sql-server-is-there-a-way-to-atomically-increment-a-column-being-used-a –