SQL Server'da “with (nolock)” nedir?


610

Birisi with (nolock)sorgular üzerinde kullanmanın etkilerini , ne zaman kullanmanız / kullanmamanız gerektiğini açıklayabilir mi?

Örneğin, yüksek işlem oranlarına ve belirli tablolarda çok fazla veriye sahip bir bankacılık uygulamanız varsa, ne tür sorgularda sorun olmaz? Her zaman kullanmanız / asla kullanmamanız gereken durumlar var mı?



1
burada bir bağlantı - mssqltips.com/sqlservertip/2470/…
Steam

Yanıtlar:


461

WITH (NOLOCK), bir işlem yalıtım düzeyi olarak READ UNCOMMITED kullanmanın eşdeğeridir. Böylece, daha sonra geri alınan, yani veritabanına hiç girmemiş veriler gibi sıralanmamış bir satırı okuma riski vardır. Bu nedenle, okumaların diğer işlemler tarafından kilitlenmesini önleyebilse de, bir riskle birlikte gelir. Yüksek işlem oranlarına sahip bir bankacılık uygulamasında, muhtemelen IMHO ile çözmeye çalıştığınız herhangi bir sorun için doğru çözüm olmayacaktır.


156
Çoğu bankacılık uygulaması, iş anlamında işlemsel oldukları için nolock'u güvenle kullanabilir. Sadece yeni satırlar yazıyorsunuz, asla güncellemiyorsunuz.
Jonathan Allen

49
@ Grauenwolf- Girilen ancak taahhüt edilmeyen bir satır hala kirli okumalara neden olabilir.
saasman

16
@ Saasman- İşlemleri geri almazsanız, bu önemli değil. Ve yalnızca eklenebilir bir tabloyla, geri alma şansı hiçbiri için ince değildir. Ve eğer gerçekleşirse, yine de gün sonunda varyans raporunda düzeltirsiniz.
Jonathan Allen

1
Yerleşikim. Üzerinde kilit ipucu eklenmediğini varsayıyorum. Örnek:
Ross Bush

11
Bir NOLOCKile kullanırsanız , SELECTbir seçim yaparken tabloya veri eklenirse (veya güncellenirse) aynı satırları bir kereden fazla (çoğaltılmış veri) döndürme riski taşırsınız.
Ian Boyd

170

Soru daha kötü olan şey:

  • bir kilitlenme veya
  • yanlış bir değer?

Finansal veritabanları için çıkmazlar yanlış değerlerden çok daha kötüdür. Bunun geri geldiğini biliyorum, ama beni dinle. DB işlemlerinin geleneksel örneği, bir satırdan çıkarma ve diğerine ekleme yapan iki satırı güncellemenizdir. Bu yanlış.

Finansal bir veritabanında ticari işlemleri kullanırsınız. Bu, her hesaba bir satır eklemek anlamına gelir. Bu işlemlerin tamamlanması ve satırların başarıyla yazılması son derece önemlidir.

Hesap bakiyesini geçici olarak yanlış yapmak büyük bir sorun değil, gün sonu mutabakatı bunun için. Ayrıca, iki ATM'nin bir veritabanından izin verilmeyen bir okumadan bir kerede kullanıldığından, bir hesaptan kredili mevduatın gerçekleşme olasılığı daha yüksektir.

Bununla birlikte, SQL Server 2005 NOLOCKgerekli olan hataların çoğunu düzeltti . Bu nedenle, SQL Server 2000 veya önceki bir sürümünü kullanmıyorsanız, buna ihtiyacınız olmamalıdır.

Daha fazla Okuma
satır düzeyi Sürüm


22
Bir hesap bakiyesinin geçici olarak yanlış olması büyük bir sorun değil mi? Bu işlem herhangi bir limit aşım limiti olmadan bir atm'den nakit çektiğiniz işlemse?
öğrenme

13
@Öğrenme: Birisi kartınızdan çekim yapmadan 30 saniye önce parayı çıkarırsanız ne olur? Tüm iletişim çok hızlı bir şekilde gerçekleşene kadar, kredili mevduat hesapları hayatın bir gerçeği olacaktır.
Jonathan Allen

6
+1 Finansal uygulamada (her yerde, sadece bankalarda değil), güncelleme veya silme işlemleri yoktur. Yanlış işlemler bile kayıtlar eklenerek düzeltilir. İngilizce'de bu terim nedir? "Storno" mu? Google bu soruya cevap vermeme yardımcı olmadı
Gennady Vanin Геннадий Ванин

7
Geç giriş ... kilitlenmeler yakalanmalı ve yeniden denenmelidir. Kirli okumaların sonuçları var
gbn

4
@JonathanAllen sadece bir fyi, terim en yüksek, UP değil.
Jimmy D

57

Ne yazık ki bu sadece taahhüt edilmemiş verileri okumakla ilgili değil. Arka planda iki kez (bir sayfa bölünmesi durumunda) sayfaları okuyabilir veya sayfaları tamamen özleyebilirsiniz. Bu nedenle sonuçlarınız büyük ölçüde çarpık olabilir.

Itzik Ben-Gan'ın makalesine göz atın . İşte bir alıntı:

"NOLOCK ipucu ile (ya da oturumun yalıtım düzeyini OKUYUNSUZ OKUYUN) olarak ayarlayarak SQL Server'a tutarlılık beklemediğinizi söylersiniz, bu nedenle garanti yoktur." Tutarsız verilerin "yalnızca daha sonra geri alınmış olan taahhüt edilmemiş değişiklikler veya işlemin bir ara durumunda veri değişiklikleri görebilirsiniz.Ayrıca, basit bir sorguda tüm tablo / dizin verilerini tarayan SQL Server'ın tarama konumunu kaybedebileceği veya aynı satırı iki kez alıyorum . "


5
Biraz daha aşağı, aynı satırı iki kez nasıl alacağını açıklar: T1 tablosunu, col1'deki kümelenmiş dizin, IGNORE_DUP_KEY seçeneğiyle benzersiz bir dizin olarak tanımlanacak şekilde yeniden oluşturacağım. Bu, col1'de yinelenen değerlerin bulunamayacağı ve yinelenen bir anahtar ekleme girişiminin işlemde başarısız olmayacağı ve bir hata oluşturduğu yerine bir uyarı oluşturduğu anlamına gelir. Bu tuhaf seçeneği kullanmazsanız, muhtemelen iki kez satır alma konusunda endişelenmenize gerek yoktur
JanHudecek

Kablolu seçenek olmadan da dupe satırları alabilirsiniz - örneğin, sorgunuz benzersiz olmayan bir dizinden yararlanıyorsa. Bu nolock'a özgü değil.
RMD

54

Nolock ipucunun yasal kullanımı için ders kitabı örneği, yüksek güncellemeli OLTP veritabanına karşı rapor örneklemesidir.

Topikal bir örnek almak. ABD'deki büyük bir cadde bankası, bankada çalıştırılan bir şehir seviyesinin ilk işaretlerini arayan saatlik bir rapor çalıştırmak isterse, bir kilit açma sorgusu, nakit mevduat ve şehir başına nakit çekimlerini toplayan işlem tablolarını tarayabilir. Böyle bir rapor için, geri alınan güncelleme işlemlerinin neden olduğu küçük hata yüzdesi raporun değerini azaltmaz.


31

Finansal işlemleri veritabanı işlemlerinde neden sarmadığınızdan emin değilsiniz (bir hesaptan diğerine para aktarırken olduğu gibi - işlemin bir tarafını bir seferde işlemezsiniz - bu yüzden açık işlemler vardır). Kodunuz göründüğü gibi ticari işlemlere karşı cesur olsa bile, tüm işlem veritabanlarının hata veya hata durumunda örtülü geri alma potansiyeli vardır. Bence bu tartışma başının çok üstünde.

Kilitleme sorunlarınız varsa, sürüm oluşturmayı uygulayın ve kodunuzu temizleyin.

Kilit yok sadece yanlış değerler döndürmez, aynı zamanda fantom kayıtlarını ve kopyalarını döndürür.

Sorguların her zaman daha hızlı çalışmasını sağlaması yaygın bir yanılgıdır. Bir tabloda yazma kilidi yoksa, herhangi bir fark yaratmaz. Masada kilitler varsa, sorguyu daha hızlı hale getirebilir, ancak kilitlerin ilk başta icat edilmesinin bir nedeni vardır.

Adil olmak gerekirse, burada bir nolock ipucunun fayda sağlayabileceği iki özel senaryo vardır

1) Canlı OLTP veritabanına karşı uzun sorgu çalıştırması gereken 2005 öncesi sql sunucusu veritabanı bu tek yol olabilir

2) Kayıtları kilitleyen ve kontrolü kullanıcı arayüzüne döndüren kötü yazılmış uygulama, okuyucular süresiz olarak engellenir. Nolock, uygulama düzeltilemiyorsa (üçüncü taraf vb.) Ve veritabanı 2005 öncesi veya sürüm oluşturma özelliği açılamıyorsa yardımcı olabilir.


11
NOLOCK'un kötü yazılmış kodu telafi etmek için kullanılmaması gerektiğine katılıyorum. Ancak, sanırım Johnathan saldırısı, veritabanı işlemlerinden hiç bahsetmediği için haksız . Sadece finansal uygulamaların kayıtlarda düzenlemelere izin vermediğine işaret ediyordu (bazı istisnalar olduğu açıktır). Fon transferi örneğinizde, bir hesap defterine borç / kredi girişi eklemek yerine hesabın bakiyesinin değerini değiştirmenin garip olacağını söylüyor .
chrnola

19
Farklı bankalarda bir hesaptan diğerine para aktarıldığında ne olacağını düşünüyorsunuz? Bazı uber-veritabanı Bank of America ve diğeri Wells Fargo'daki bir masaya kilitleniyor mu? Hayır. Her birine bir finansal işlem yazılır ve gün sonu süreci, tüm kayıtların eşleştiğini doğrular.
Jonathan Allen

24

NOLOCKeşdeğer olduğunu READ UNCOMMITTED, ancak Microsoft, için kullanmak gerektiğini söylüyor UPDATEya DELETEtabloların:

UPDATE veya DELETE deyimleri için: Bu özellik, Microsoft SQL Server'ın gelecekteki bir sürümünde kaldırılacaktır. Bu özelliği yeni geliştirme çalışmalarında kullanmaktan kaçının ve şu anda bu özelliği kullanan uygulamaları değiştirmeyi planlayın.

http://msdn.microsoft.com/en-us/library/ms187373.aspx

Bu makale, SQL Server 2005 için geçerlidir, bu nedenle NOLOCKbu sürümü kullanıyorsanız desteği vardır. Gelecekteki kanıtlarınızı kodlamak için (kirli okumalar kullanmaya karar verdiğinizi varsayarak) bunu saklı yordamlarınızda kullanabilirsiniz:

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED


21

Yalnızca verileri okurken kullanabilirsiniz ve henüz işlenmemiş verileri geri alıp almadığınızı gerçekten umursamıyorsunuzdur.

Bir okuma işleminde daha hızlı olabilir, ama gerçekten ne kadar olduğunu söyleyemem.

Genel olarak, kullanmaya karşı öneriyorum - taahhüt edilmemiş verileri okumak en iyi ihtimalle biraz kafa karıştırıcı olabilir.


1
SQL Server 2005'in satır sürümüne sahip olduğundan bahsetmiş olursanız iyi olur, böylece nolocks artık gerekli değildir.
Jonathan Allen

Peki, "with (nolock)" hala SQL Server 2005'te bile yerini alıyor - ama faydalar gittikçe inceliyor, bu doğru.
marc_s

18

Genellikle iyi olduğu başka bir durum, verilerin belki de önceden yaşlandığı ve yazılmadığı bir raporlama veritabanındadır. Ancak bu durumda, seçenek varsayılan yalıtım düzeyi değiştirilerek yönetici tarafından veritabanı veya tablo düzeyinde ayarlanmalıdır.

Genel durumda: Eğer olduğunda kullanabilirsiniz çok emin eski verileri okumak için sorun olmadığını. Hatırlanması gereken önemli şey , yanlış anlamanın çok kolay olmasıdır . Örneğin, sorguyu yazdığınız sırada sorun olmasa bile, bu güncelleştirmeleri daha önemli hale getirmek için gelecekte veritabanında bir şeyin değişmeyeceğinden emin misiniz?

Ayrıca bankacılık uygulamasında muhtemelen iyi bir fikir olmadığı fikrini 2. kazanacağım . Veya envanter uygulaması. Veya işlemler hakkında düşündüğünüz herhangi bir yer.


4
Bankacılık uygulamaları üzerinde çalışan bir kişi olarak, no-lock'ların sorun olmadığını söylemeliyim. İşlem kayıtları, yani eklenen ancak asla güncellenmeyen veya silinmeyen satırlar, kaydedilmemiş verilerin okunması sorunlarına şaşırtıcı derecede dirençlidir.
Jonathan Allen

15

Basit yanıt - SQL'iniz veri değiştirmediğinde ve diğer etkinlikleri engelleyebilecek bir sorgunuz olduğunda (kilitleme yoluyla).

Raporlar için kullanılan herhangi bir sorgu için, özellikle de sorgu 1 saniyeden uzun sürerse, dikkate değer.

Bir OLTP veritabanında çalıştırdığınız OLAP türü raporlarınız varsa özellikle kullanışlıdır.

Yine de sorulması gereken ilk soru "neden bu konuda endişeleniyorum?" Deneyimlerime göre, varsayılan kilitleme davranışını geçiştirmek genellikle birisi "herhangi bir şey denemek" modundayken gerçekleşir ve bu beklenmedik sonuçların olası olmadığı bir durumdur. Çoğu zaman erken bir optimizasyon örneğidir ve "her ihtimale karşı" bir uygulamaya kolayca gömülebilir. Bunu neden yaptığınızı, hangi sorunu çözdüğünü ve sorunun gerçekten olup olmadığını anlamak önemlidir.


11

Kısa cevap:

Yalnızca WITH (NOLOCK)kümelenmiş dizini olan tablolarda SELECT deyiminde kullanın .

Uzun cevap:

WITH (NOLOCK) genellikle veritabanı okumalarını hızlandırmak için sihirli bir yol olarak kullanılır.

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

Kümelenmemiş bir dizine sahip bir tabloya WITH (NOLOCK) uygulanırsa, satır verileri sonuç tablosuna aktarılırken satır dizinleri diğer işlemler tarafından değiştirilebilir. Bu, sonuç kümesinin satır eksik olabileceği veya aynı satırı birden çok kez görüntüleyebileceği anlamına gelir.

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


2
Kesin olmayan verileri okumak, nihai kararı değiştirmezse kabul edilebilir. Örneğin, perakende mağazanızın önümüzdeki 6 ay boyunca ne kadar para kazanacağını tahmin etmeye çalışıyorsanız, Tammy'nin gerçekten 3 aldığında 2 rulo kağıt havlu aldığını görünce, gelecek fikrinizi değiştirmeyecek .
Jonathan Allen

1
Filtreniz şimdi içeriyorsa, sorguyu çalıştırdığınız anda verileriniz yanlış olacaktır. Filtreniz yalnızca geçmiş verileri içeriyorsa, kullanmak verileri READ UNCOMITTED hiç etkilemez. ANSI standardına dahil edilmesinin bir nedeni vardır.
Jonathan Allen

2
Asla asla Deme. Verilerin% 100 doğru olması gerekiyorsa, nolock kullanmamalısınız. Benim için genellikle böyle değil. Bir kullanıcıya veri sunarken, veriler üzerinde hareket ettikleri zaman, zaten zaten değişmiş olabilir, ancak büyük olasılıkla değişmemiş olabilir ve kilit çekişmesi yanıt gecikmelerine değmez.
Perposterer

Var olmaya değer sistemlere bağlı kalalım. Tammy'nin mükemmel derecede iyi bir beyni olduğunu unutmayın, bu yüzden kimsenin herhangi bir şey fark etmediği küçük kağıt havlu alımlarını kaydetmek için bir veritabanı kullanmak en saçmadır. Odak noktamız aslında önemli olan sistemlerdir, örneğin insanların zamanında ödeme yapması, acil durumlara cevap vermesi vb. Bir kişi bir veritabanından daha iyi bir iş yapabildiğinde, bu kaynakları yeniden kullanmayı düşünün.
WonderWorker

10

Benim 2 sent - kullanmak mantıklı WITH (NOLOCK) raporlar oluşturmak gerektiğinde. Bu noktada, veriler çok fazla değişmez ve bu kayıtları kilitlemek istemezsiniz.


2
Mevcut değişiklikleri umursamıyorsanız WITH (NoLOCK) ile daha iyi olduğunu düşünüyorum.
Abdul Saboor

9

Finans işlemlerini yürütüyorsanız asla kullanmak istemeyeceksiniz nolock. nolocken iyi, çok sayıda güncellemeye sahip büyük tablolar arasından seçim yapmak için kullanılır ve aldığınız kaydın güncelliğini yitirmiş olması önemli değildir.

Finansal kayıtlar için (ve çoğu uygulamadaki hemen hemen tüm diğer kayıtlar) nolock, yazılmakta olan bir kayıttan potansiyel olarak verileri okuyabildiğiniz ve doğru verileri alamadığınız için tahribat yaratacaktır.


5
Şaşırtıcı bir şekilde, finansal verilerle çalışırken bu bir sorun değildir. Satırlar hiçbir zaman düzenlenmediği ve gün sonunda hesaplar mutabakat edildiği için geçici olarak sahte verileri okumak hiçbir şey yapmaz.
Jonathan Allen

8

Yapacağım şeyler için bir "sonraki parti" alırdım. Bu durumda hangi öğenin olduğu önemli değil ve aynı sorguyu çalıştıran birçok kullanıcı var.


1
Yapacağımız iş kuyruğuyla arka plan görevi sunmak için benzer bir şey yapıyoruz. Belirli bir kayda ulaştığında artık mevcut değilse / seçim ölçütleriyle eşleşiyorsa, yalnızca bir sonrakine geçer.
TripeHound

7

"Kirli" verilerle uyumlu olduğunuzda nolock kullanın. Bu, nolock'un değiştirilme ve / veya taahhüt edilmeyen verilerdeki verileri okuyabileceği anlamına gelir.

Genellikle yüksek işlem ortamında kullanmak iyi bir fikir değildir ve bu yüzden sorguda varsayılan bir seçenek değildir.


3
İhtiyacınız olan tek zaman yüksek işlem ortamında. Tablolarınız çoğunlukla boştaysa, o zaman hiçbir şey kazanamazsınız.
Jonathan Allen

7

Özellikle yüksek aktiviteye sahip SQLServer 2000 veritabanlarında (nolock) ipucu ile kullanıyorum. Ancak SQL Server 2005'te gerekli olduğundan emin değilim. Yakın zamanda bir SQL Server 2000'de istemcinin DBA'sının isteği üzerine bu ipucunu ekledim, çünkü çok fazla SPID kayıt kilidi fark ediyordu.

Söyleyebileceğim tek şey ipucu kullanmak bize zarar vermedi ve kilitleme sorunu kendini çözmüş gibi görünüyor. Söz konusu müşterideki DBA temel olarak ipucunu kullanmamız konusunda ısrar etti.

Bu arada, ele aldığım veritabanları kurumsal tıbbi talep sistemlerinin arka uçlarıdır, bu yüzden birçok katılımda milyonlarca kayıt ve 20'den fazla tablodan bahsediyoruz. Genellikle birleşimdeki her tablo için bir WITH (nolock) ipucu eklerim (türetilmiş bir tablo olmadığı sürece, bu durumda bu ipucunu kullanamazsınız)


1
SQL Server 2005, nolocks ihtiyacını büyük ölçüde azaltması gereken "satır sürümü" ekledi. Kısa bir süre önce yeni sürüme geçtik ve DBA'larımızı kullanmayı bırakacak şekilde eğitilmiyoruz.
Jonathan Allen

5

En basit cevap basit bir soru - sonuçlarınızın tekrarlanabilir olması gerekiyor mu? Evet ise, NOLOCKS hiçbir koşulda uygun değildir

Tekrarlanabilirliğe ihtiyacınız yoksa, özellikle hedef veritabanına bağlanan tüm işlemler üzerinde kontrolünüz yoksa, nolocks yararlı olabilir.

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.