NOLOCK (Sql Server ipucu) kötü bir uygulama mı?


125

Kritik olmayan web sitesi ve uygulamaları yapma işindeyim -> örn. bankacılık yazılımı, uzay uçuşu, yoğun bakım izleme uygulaması vb. fikri anladınız.

Öyleyse, bu büyük feragatname ile, bazı Sql ifadelerinde NOLOCK ipucunu kullanmak kötü mü? Birkaç yıl önce, bir Sql Yöneticisi tarafından, "kirli okumadan" memnun kalırsam, NOLOCK'u kullanmam gerektiği önerilmişti, bu da bana sistemimden biraz daha fazla performans sağlayacak çünkü her okuma, tablo / satır / ne olursa olsun.

Ayrıca, kilitlenme sorunu yaşıyorsam bunun harika bir çözüm olduğu söylendi. Bu yüzden, bir Sql gurusu bana rastgele bir kodla yardım edene ve sql kodumdaki tüm NOLOCKS'leri fark edene kadar birkaç yıl boyunca bu düşünceyi izlemeye başladım. Kibarca azarlandım ve bunu bana açıklamaya çalıştı (neden iyi bir şey değil) ve kayboldum. Açıklamasının özünün 'daha ciddi bir soruna yara bandı çözümü olduğunu hissettim ... özellikle de çıkmaz yaşıyorsanız. Bu nedenle, sorunun kökenini düzeltin '.

Son zamanlarda bu konuda biraz googling yaptım ve bu yazıya rastladım .

Peki, bazı sql db guru sensei'ler beni aydınlatabilir mi?


Anlayamıyorum Sam, yoğun okunan bir web sitesiyse Anlık Görüntü izolasyonunu kullan diyorsun. Ama sonra bunu SO yaptım diyorsun ve kötü mü? veya sadece NOLOCK kullanımları?
Pure.Krome

Yanıtlar:


67

NOLOCK ipucu ile, ifade için işlem yalıtım düzeyi şu SELECTşekildedir:READ UNCOMMITTED . Bu, sorgunun kirli ve tutarsız veriler görebileceği anlamına gelir.

Bu, kural olarak uygulamak için iyi bir fikir değildir. Bu kirli okuma davranışı, kritik web tabanlı uygulamanız için uygun olsa bile, bir NOLOCK taraması, kilitleme korumasının olmaması nedeniyle veri hareketi nedeniyle sorguyu sonlandıracak 601 hatasına neden olabilir.

Anlık Görüntü İzolasyonu Yardımcı Olduğunda ve Zarar Verdiğinde Okumayı öneririm - MSDN, çoğu koşulda SNAPSHOT yerine OKUMA İŞLEMLİ SNAPSHOT kullanılmasını önerir.


1
Rex, lütfen anlık görüntü izolasyonu hakkında bir not eklemekten çekinmeyin.
Sam Saffron

2
Evet, Sam Snapshot izolasyon diyor ve siz de Committed Snapshot'u Okuyun. Kafam çok karıştı: P (ve makalelere de henüz
girmedim

2
Ara sıra faydalıdır, ancak normalde üretim için değildir. Bunu sıklıkla, kirli bir okumanın önemli olmayacağı kaba büyüklük sırasını önemsediğim raporlarla veya test etmek için bir veri örneğini çıkarmak için kullanıyorum.
TimothyAWiseman

NOLOCK == kaydedilmiş satırların kaçırılıp atlanmaması, yüklenmemiş satırların dahil edilmesi, nadir durumlarda aynı satırın birden çok kez döndürülmesi ve çok nadir durumlarda sorgumla eşleşmeyen satırların döndürülmesi umurumda değil. ( bu konudaki başka bir SO q'n'dan bulunan blogs.msdn.com/b/sqlcat/archive/2007/02/01/… bakın )
Andrew Hill

106

Yığın taşması çalışma öncesinde, ben karşıydım NOLOCKpotansiyel bir performans ilkesi temellerinde SELECTile NOLOCKve tarih veya tutarsız yitirmiş olabilir verilerle sonuçları geri almak. Düşünülmesi gereken bir faktör, aynı anda kaç kaydın eklenebileceği / güncellenebileceğidir, başka bir işlem aynı tablodan veri seçiyor olabilir. Bu çok sık meydana gelirse, aşağıdaki gibi bir veritabanı modu kullanmadığınız sürece yüksek kilitlenme olasılığı vardır.READ COMMITED SNAPSHOT .

O zamandan beri, NOLOCKnasıl geliştirilebileceğine tanık olduktan sonra kullanımına bakış açımı değiştirdim.SELECT performansı ve çok yüklü bir SQL Server'daki kilitlenmeleri ortadan kaldırmaya . Verilerinizin tam olarak% 100 işlenmemiş olmasını umursamayabileceğiniz zamanlar olabilir ve güncel olmadıkları halde sonuçları hızlı bir şekilde geri almanız gerekir.

Kullanmayı düşünürken kendinize bir soru sorun NOLOCK:

Sorgum çok sayıda INSERT/ UPDATEkomutu olan bir tablo içeriyor mu ve bir sorgudan döndürülen verilerin belirli bir anda bu değişikliklerin eksik olmasıyla ilgilenir miyim?

Cevap hayır ise, NOLOCKperformansı artırmak için kullanın .


NOLOCKStack Overflow kod tabanında anahtar kelime için hızlı bir arama yaptım ve 138 örnek buldum, bu yüzden onu epeyce yerde kullanıyoruz.


7
IMO, Bu biraz basit. Deadlocks, örtücü indeksler kullanılarak Kümelenmiş indeksten baskı alınarak kaldırılabilir.
Mitch Wheat

8
İyi bir dizin kapsamının önemini azaltmak istemiyorum. NOLOCK kullanan sorguların, çok sayıda ekleme / güncelleme içeren tablolardaki dizinlerle gerçekleştirilen kazanımlara ek performans ekleyebileceği zamanlar vardır. Stack Overflow'da sorgu hızı, hatalı veya eksik veriler pahasına olsa bile çok önemlidir.
Geoff Dalgas

9
Görünüşe göre , kullanarak yinelenen satırlar elde edilebilir NOLOCK. Bu, cevabınıza olumsuz oy vermem gerektiği anlamına geliyor. Afedersiniz.
ErikE

1
@MitchWheat A SELECT, yalnızca bir örtme indeksinden okuma, bir kilitlenmeye neden olabilir. SPID 1) SELECTkaplama indeksinden a başlatır . SPID 2) UPDATETablonun bir bölümünü başlatın . Güncelleme daha sonra kaplama indeksini güncellemeye geçer. UPDATEtarafından kilitlenmiş bir dizin aralığına ulaşır SELECTve engellenir. SPID 1) hala kapsama dizinini arıyor, tarafından kilitlenmiş bir aralık bulur UPDATEve engellenir. DEADLOCK . Bu kilitlenmeyi hiçbir şey çözemez (SQL Server hatası 1205'i yakalamak ve otomatik olarak yeniden denemek veya kullanmak dışında NOLOCK)
Ian Boyd

2
Bence bu cevapla ilgili dikkat edilmesi gereken en önemli şey , soruna uygun olduğudur . Uygulamanıza bağlı olarak, eski / taahhüt edilmemiş / yinelenen / eksik veri riski, ödün vermeye değmeyebilir.
Bütünsel Geliştirici

20

Kirli okumaları umursamıyorsanız (yani ağırlıklı olarak OKU durumunda), o NOLOCKzaman sorun değil.

ANCAK , kilitleme sorunlarının çoğunun, sorgu iş yükünüz için 'doğru' dizinlere sahip olmamaktan kaynaklandığını unutmayın (donanımın göreve bağlı olduğu varsayılarak).

Ve gurunun açıklaması doğruydu. Genellikle daha ciddi bir soruna yara bandı çözümüdür.

Düzenleme : Kesinlikle NOLOCK'un kullanılması gerektiğini önermiyorum. Sanırım bunu açıkça belirtmeliydim. (Sadece iyi olduğunu analiz ettiğim aşırı durumlarda kullanırdım). Örnek olarak, bir süre önce kilitleme sorunlarını denemek ve hafifletmek için NOLOCK serpilmiş bazı TSQL üzerinde çalıştım. Hepsini kaldırdım, doğru dizinleri uyguladım ve TÜM kilitlenmeler ortadan kalktı.


3
Hmm .. Hala anlamadım. Yani sorun değil, ama aynı zamanda kötü bir form .. demek istediğin bu mu?
Pure.Krome

Kirli okumaları ASLA umursamadığınız varsayılırsa, o zaman canınızı yakmaz. ANCAK bu genellikle semptomun tedavisi ile ilgili bir durumdur, nedeni değildir ...
Mitch Wheat

2
Pekala, adil rexem'in henüz reddedildiğini düşünmüyorum, bence nolock kullandığınızda ortaya çıkan keyfi hataları ele almadınız. Web sitenizde ara sıra boş bir hata sayfası almanız iyi değil, gerçekten kötü bir form. "Kirli şeyleri umursamıyorsan iyi okur" iddiasından hoşlanmıyorum ... kirli okumaları umursamasan bile iyi değil
Sam Saffron

Bir sorgu yeniden deneme mantığını uygulamadığınız bir istisna oluşturduğunda aldığınız boş sayfa. Bir istisna ile sorgu yürütme sonuçlandığında sitelerinizde ne olur, her yerde mantığı yeniden deniyor musunuz?
Sam Saffron

Uygun dizinlere ulaştığını bildiğiniz çok iyi optimize edilmiş bir sorguyu ele alın. Sonra kilitlenmeyen ipuçları ekleyin ve hızlanmasını izleyin. Kirli okumaları umursamıyorsanız, nolock kullanarak asla kendinize zarar vermezsiniz.
Hardwareguy

13

Yüksek trafikte herhangi bir deneyimi olan bir "guru" olduğundan şüphe ...

Web siteleri, kişi tamamen yüklenmiş sayfayı görüntülediğinde genellikle "kirli" olur. Veritabanından yüklenen ve ardından düzenlenen verileri kaydeden bir form düşünün. İnsanların kirli okumalara bu kadar hayır demesi aptalca.

Bununla birlikte, seçimlerinizi oluşturan birkaç katmanınız varsa, tehlikeli bir fazlalık oluşturuyor olabilirsiniz. Para veya durum senaryolarıyla uğraşıyorsanız, sadece işlemsel veri okuma / yazma değil, aynı zamanda uygun bir eşzamanlılık çözümüne (çoğu "guru" nun uğraşmadığı bir şey) ihtiyacınız vardır.

Öte yandan, bir web sitesi için gelişmiş bir ürün aramanız varsa (yani, muhtemelen önbelleğe alınmayacak ve biraz yoğun olmayacak bir şey) ve birkaç eşzamanlı kullanıcısı olan bir site oluşturduysanız (fenominal kaç tane "uzmanlar" değil), arkasındaki diğer tüm süreçleri daraltmak saçmadır.

Ne anlama geldiğini bilin ve uygun olduğunda kullanın. Veritabanınız bugünlerde neredeyse her zaman en büyük baş belanız olacak ve NOLOCK'u kullanma konusunda akıllı olmak sizi altyapıdan binlerce kurtarabilir.

DÜZENLEME: Bu sadece kilitlenmeler değil, aynı zamanda herkesi bitirene kadar bekleteceğiniz ya da tam tersi.

EF4'te NOLOCK İpucu mu kullanıyorsunuz?


10

Cevapların hiçbiri yanlış değil, ancak biraz kafa karıştırıcı olabilir.

  • Tekil değerleri / satırları sorgularken, NOLOCK'u kullanmak her zaman kötü bir uygulamadır - muhtemelen asla yanlış bilgi görüntülemek veya hatta yanlış veriler üzerinde herhangi bir işlem yapmak istemezsiniz.
  • Kaba istatistiksel bilgileri görüntülerken, NOLOCK çok faydalı olabilir. Örnek olarak SO atın: Okumak için kilitleri almak saçma olur kesin bir soruya ya da bir etiket için sorular tam sayısının Görüntüleme sayısı. Şu anda yanlış bir şekilde "sql-server" etiketli 3360 soruyu ve bir işlem geri dönüşü nedeniyle 3359 soruyu bir saniye sonra belirtmeniz kimsenin umurunda değil.

İlk fikrine hiç katılmıyorum. Tek değerleri / satırları sorguluyorsanız ve bu satır için benzersiz bir kimlik belirtiyorsanız ve başka hiçbir işlemin buna erişemeyeceğini biliyorsanız, nolock kullanmak tamamen kabul edilebilirdir ve eşzamanlı bir uygulamada engellemeyi azaltır.
tuseau

1
Hayır değil. Satır başka nedenlerle değişebilir, örneğin başka bir satır eklemek sayfayı böler. Doğru indeksleme, Read Committed Snapshot ve Snapshot Isolation neredeyse her zaman daha iyi fikirlerdir.
Mark Sowul

1
Eğer başka süreç satır erişen olacağını "bilmek" eğer @tuseau şey engellemez bir kilit alarak eylemi, peki (pratikte) hiçbir maliyeti
Andrew Hill'e

2

Profesyonel bir Geliştirici olarak buna bağlı olduğunu söyleyebilirim. Ama kesinlikle GATS ve OMG Ponies tavsiyelerine uyuyorum. Ne yaptığınızı bilin, ne zaman yardımcı olduğunu ve ne zaman acıdığını bilin ve

ipuçlarını ve diğer kötü fikirleri okuyun

Sql sunucusunu daha derinlemesine anlamanıza ne sağlayabilir. Genelde SQL İpuçları KÖTÜ'dür kuralını uygularım, ancak ne yazık ki bunları ara sıra kullanıyorum ve sonra SQL sunucusunu zorlamaktan bıktığımda bir şeyler yapıyorum ... Ama bunlar nadir görülen durumlar.

luke


2

Uygulama desteği, SSMS kullanarak üretim sunucusundan gelen reklam sorgularını yanıtlamak istediğinde (bu, raporlama yoluyla karşılanmadı) nolock kullanmalarını istedim. Bu şekilde 'ana' iş etkilenmez.


2

NOLOCK ipucu hakkındaki bazı yorumlara ve özellikle "uygun olduğunda kullanın" diyenlere katılıyorum. Uygulama kötü yazılmışsa ve eşzamanlılığı uygun olmayan bir şekilde kullanıyorsa - bu, kilidin artmasına neden olabilir. Yüksek derecede işlemsel tablo da doğası gereği sürekli kilitleniyor. İyi bir dizin kapsamına sahip olmak verilerin alınmasına yardımcı olmaz, ancak İZOLASYON SEVİYESİNİ HABERLEŞMEDİ OKUMA olarak ayarlamak işe yarar. Ayrıca, değişikliklerin doğasının tahmin edilebilir olduğu birçok durumda NOLOCK ipucu kullanmanın güvenli olduğuna inanıyorum. Örneğin, yolcularla yapılan işler çok sayıda ölçüm eki ile farklı süreçlerden geçtiğinde üretimde, NOLOCK ipucu ile bitmiş işe karşı güvenli bir şekilde sorgu yürütebilir ve bu şekilde, PROMOTED veya EXCLUSIVE kilitleri masaya koyan diğer oturumlarla çakışmayı önleyebilirsiniz. /sayfa. Bu durumda eriştiğiniz veriler statiktir, ancak yüz milyonlarca kayıt ve dakikada binlerce güncelleme / ekleme içeren çok işlemsel bir tabloda yer alabilir. Şerefe


2

Nolock kullanmanın neredeyse hiçbir zaman doğru olmadığına inanıyorum.

Tek bir satırı okuyorsanız, doğru dizin NOLOCK'a ihtiyacınız olmayacağı anlamına gelir, çünkü bireysel satır eylemleri hızlı bir şekilde tamamlanır.

Geçici gösterim dışında herhangi bir şey için çok sayıda satır okuyorsanız ve sonucu tekrarlayabilmeyi önemsiyorsanız veya üretilen sayıya göre savunma yapıyorsanız, NOLOCK uygun değildir.

NOLOCK, "Bu yanıtın yinelenen satırlar, silinmiş satırlar veya geri alma nedeniyle başlamak için asla eklenmemiş satırlar içermesi umrumda değil" için bir vekil etikettir.

NOLOCK altında olası hatalar:

  • Eşleşen satırlar hiç döndürülmez.
  • tek satırlar birden çok kez döndürülür (aynı birincil anahtarın birden çok örneği dahil)
  • Eşleşmeyen satırlar döndürülür.

NoLock select çalışırken sayfanın bölünmesine neden olabilecek herhangi bir eylem, bunların meydana gelmesine neden olabilir. Hemen hemen her eylem (silme bile) bir sayfanın bölünmesine neden olabilir.

Bu nedenle: Çalışırken satırın değiştirilmeyeceğini "biliyorsanız", indeks verimli bir erişime izin vereceği için nolock kullanmayın.

Sorgu çalışırken satırın değişebileceğinden şüpheleniyorsanız ve doğruluğu önemsiyorsanız, nolock kullanmayın.

Kilitlenmeler nedeniyle NOLOCK'u düşünüyorsanız, beklenmedik tablo taramaları için sorgu planı yapısını inceleyin, kilitlenmeleri izleyin ve neden oluştuğunu görün. Yazılar etrafında NOLOCK, önceden kilitlenmiş sorguların potansiyel olarak her ikisinin de yanlış cevabı yazacağı anlamına gelebilir.


2

Mümkün olduğunda daha iyi çözümler şunlardır:

  • Verilerinizi (günlük çoğaltmayı kullanarak) bir raporlama veritabanına kopyalayın.
  • SAN anlık görüntülerini kullanın ve DB'nin tutarlı bir sürümünü bağlayın
  • Daha iyi bir temel işlem izolasyon seviyesine sahip bir veritabanı kullanın

SNAPSHOT işlem izolasyon düzeyi, MS'nin Oracle'a olan satışlarını kaybetmesi nedeniyle oluşturuldu. Oracle, bu sorunu önlemek için geri alma / yineleme günlüklerini kullanır. Postgres, MVCC kullanır. Gelecekte MS Heckaton, MVCC'yi kullanacak, ancak bu, üretime hazır olmaktan yıllar sonra.


Yukarıda bir yazım hatası var. "Daha iyi temel işlem izolasyon mekanizması" demek istiyorum.
pwy

1
SNAPSHOT işlem izolasyon seviyesi MS'in buluşudur. Temel olarak, verileri TEMPDB'de bir geçici tabloya koyar. Bu DB, kutudaki tüm DB'ler arasında paylaşılır. Bu nedenle, mümkün olduğunda TEMPDB için SSD'leri kullanmak isteyeceksiniz. Bu muhtemelen diğer seçeneklerden daha az çaba gerektirir.
pwy

1

NOLOCK genellikle veritabanı okumalarını hızlandırmanın sihirli bir yolu olarak kullanılır, ancak mümkün olan her yerde kullanmaktan kaçınmaya çalışıyorum.

Sonuç kümesi, henüz işlenmemiş ve genellikle daha sonra geri alınan satırları içerebilir.

Bir hata veya Sonuç kümesi boş olabilir, satırlar eksik olabilir veya aynı satırı birden çok kez görüntüleyebilir.

Bunun nedeni, diğer işlemlerin verileri sizin okurken aynı anda taşımasıdır.

READ COMMITTED, birden çok kullanıcının aynı hücreyi aynı anda değiştirdiği tek bir sütunda verilerin bozulmasına ek bir sorun ekler.


-2

Önceden yazılmış sistemlerle karşılaştığınız ve tablolara indeksler eklediğinizde, 14 giglik bir veri tablosunun veri yüklemesini büyük ölçüde yavaşlattığı gerçek hayatta, bazen raporlarınızda NOLOCK İLE kullanmak zorunda kalırsınız ve ay sonu işlemlerinde toplu işlevler (toplam , sayım vb.) satır, sayfa, tablo kilitleme yapmayın ve genel performansı bozmayın. Söylemesi kolay yeni bir sistemde asla NOLOCK İLE kullanmayın ve dizinleri kullanın - ancak dizinler eklemek veri yüklemesini ciddi şekilde düşürür ve bana söylendiğinde, dizinleri silmek için kod tabanını değiştirin, ardından toplu yükleme ve ardından dizinleri yeniden oluşturun - ki yeni bir sistem geliştiriyorsanız, her şey yolunda ve iyidir. Ama zaten bir sisteminiz olduğunda değil.


1
ne diyorsun
Max Alexander Hanna
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.