NOLOCK (Sql Server 힌트)이 나쁜 습관입니까?


125

나는 업무에 중요 하지 않은 웹 사이트 및 응용 프로그램을 만드는 사업을하고 있습니다 . 뱅킹 소프트웨어, 우주 비행, 중환자 실 모니터링 애플리케이션 등 아이디어를 얻을 수 있습니다.

그래서, 그 거대한 면책 ​​조항과 함께 일부 SQL 문에서 NOLOCK 힌트를 사용하는 것이 나쁘습니까? 몇 년 전에 동료 Sql 관리자가 "더티 읽기"에 만족하면 NOLOCK을 사용해야한다고 제안했습니다. "더티 읽기"에 만족하면 각 읽기가 잠금을 해제하지 않기 때문에 시스템 성능이 조금 더 향상됩니다. 테이블 / 행 / 무엇이든.

또한 교착 상태가 발생하는 경우 훌륭한 솔루션이라고 들었습니다. 그래서 Sql 전문가가 임의의 코드로 나를 돕고 SQL 코드에서 모든 NOLOCKS를 발견 할 때까지 몇 년 동안 그 생각을 따르기 시작했습니다. 나는 정중하게 꾸짖었고 그는 그것을 나에게 설명하려했고 (왜 그것이 좋지 않은지) 나는 길을 잃었습니다. 나는 그의 설명의 본질이 '더 심각한 문제에 대한 반창고 해결책이다. 특히 당신이 교착 상태를 경험하고 있다면 .. 따라서 문제의 근원을 수정하십시오. '

최근에 인터넷 검색을했고이 게시물을 보았습니다 .

그래서, 일부 SQL DB 전문가 선생님이 나를 계몽시켜 줄 수 있습니까?


이해가 안가요 샘, 읽기가 많은 웹 사이트 인 경우 스냅 샷 격리를 사용하는 것입니다. 하지만 당신은 그렇게했다고 말하고 있습니다. 아니면 NOLOCK을 사용합니까?
Pure.Krome

답변:


67

NOLOCK 힌트를 사용하는 경우 SELECT문의 트랜잭션 격리 수준 은 READ UNCOMMITTED입니다. 이것은 쿼리가 더럽고 일관성이없는 데이터를 볼 수 있음을 의미합니다.

일반적으로 적용하는 것은 좋은 생각이 아닙니다. 이 더티 읽기 동작이 미션 크리티컬 웹 기반 애플리케이션에 대해 정상인 경우에도 NOLOCK 스캔은 잠금 보호 부족으로 인해 데이터 이동으로 인해 쿼리를 종료하는 601 오류를 유발할 수 있습니다.

내가 읽어 보시기 바랍니다 스냅 샷 격리는 데 도움이되면하고 아파하는 경우 -은 MSDN은 READ 대부분의 상황에서 스냅보다는 스냅 샷을 COMMITTED 사용하는 것이 좋습니다.


1
Rex, 스냅 샷 격리에 대한 메모를 자유롭게 추가해주세요.
Sam Saffron

2
예, Sam은 Snapshot isolation을 말하고 있으며 Read Committed Snapshot을 제안합니다. 나는 너무 혼란스러워하고있다 : P (그리고 나는 아직 기사를 탐구
하지도 않았다

2
가끔 유용하지만 일반적으로 생산에는 사용되지 않습니다. 테스트 할 데이터 샘플을 추출하거나 더티 읽기가 중요하지 않은 대략적인 크기에 주로 관심이있는 보고서를 생성하는 데 자주 사용합니다.
TimothyAWiseman

NOLOCK == 커밋 된 행이 누락되었는지, 커밋되지 않은 행이 포함되는지, 드물게 동일한 행이 두 번 이상 반환되고 매우 드물게 내 쿼리와 일치하지 않는 행이 반환되는지 상관하지 않습니다. (참조 blogs.msdn.com/b/sqlcat/archive/2007/02/01/... 이 주제에 다른 SO의 q'n에서 발견)
앤드류 힐에게

106

스택 오버플로 작업을하기 전에, 나는 반대했다 NOLOCK당신이 잠재적를 수행 할 수있는 원금 SELECTNOLOCK날짜 또는 일관성이 밖으로 할 수있는 데이터와 결과를 다시 얻을. 고려해야 할 요소는 다른 프로세스가 동일한 테이블에서 데이터를 선택할 수있는 동시에 삽입 / 업데이트 될 수있는 레코드 수입니다. 이런 일이 많이 발생하면 .NET과 같은 데이터베이스 모드를 사용하지 않는 한 교착 상태가 발생할 가능성이 높습니다 READ COMMITED SNAPSHOT.

이후 대량으로로드 된 SQL Server에서 교착 상태를 제거 NOLOCK하고 SELECT성능을 향상시킬 수있는 방법 을 확인한 후 사용에 대한 관점을 변경 했습니다 . 데이터가 정확히 100 % 커밋되지 않았고 결과가 오래 되었더라도 신속하게 결과를 되 찾아야하는 경우가 있습니다.

다음을 사용할 때 스스로에게 질문하십시오 NOLOCK.

내 쿼리에 많은 수의 INSERT/ UPDATE명령 이있는 테이블이 포함 되어 있으며 쿼리에서 반환 된 데이터가 주어진 순간에 이러한 변경 사항을 누락 할 수 있는지 여부를 신경 쓰나요?

대답이 아니오이면을 사용 NOLOCK하여 성능을 향상 시키십시오.


방금 NOLOCKStack Overflow의 코드베이스 에서 키워드를 빠르게 검색 하고 138 개의 인스턴스를 찾았으므로 꽤 많은 곳에서 사용합니다.


7
IMO, 이것은 약간 단순합니다. 커버링 인덱스를 사용하여 교착 상태를 제거하고 클러스터형 인덱스의 부담을 줄일 수 있습니다.
Mitch Wheat

8
좋은 지수 커버리지의 중요성을 줄이고 싶지 않습니다. NOLOCK을 사용하는 쿼리는 많은 수의 삽입 / 업데이트가있는 테이블의 인덱스에 의해 실현되는 이점 외에 추가 성능을 추가 할 수 있습니다. Stack Overflow의 쿼리 속도는 데이터가 부정확하거나 누락 된 경우에도 가장 중요합니다.
Geoff Dalgas

9
분명히 하나는 중복 행을 얻을 수 있습니다 사용 NOLOCK. 이것은 내가 당신의 대답에 반대 투표를해야한다는 것을 의미합니다. 죄송합니다.
ErikE 2011-06-07

1
@MitchWheat A SELECT는 커버링 인덱스에서만 읽기 때문에 교착 상태가 발생할 수 있습니다. SPID 1) SELECT커버링 인덱스에서 시작합니다 . SPID 2) UPDATE테이블의 시작 . 그런 다음 업데이트는 커버링 인덱스 업데이트로 이동합니다. UPDATE에 의해 잠긴 인덱스 범위에 도달하고 SELECT차단됩니다. SPID 1) 여전히 커버링 인덱스를 검색하고에 의해 잠긴 범위를 찾고 UPDATE차단됩니다. DEADLOCK . 교착 상태를 해결할 수있는 방법은 없습니다 (SQL Server 오류 1205 포착 및 자동 재시도 또는 사용 NOLOCK제외)
Ian Boyd

2
이 답변에 대해 주목해야 할 중요한 점은 당면한 문제에 적절하다는 것 입니다. 애플리케이션에 따라 부실 / 미 확약 / 중복 / 누락 된 데이터의 위험은 절충 할 가치가 없습니다.
전체적 개발자

20

더티 읽기에 신경 쓰지 않는다면 (즉, 주로 READ 상황에서) NOLOCK괜찮습니다.

그러나 대부분의 잠금 문제는 쿼리 워크로드에 대한 '올바른'인덱스가 없기 때문입니다 (하드웨어가 작업에 달려 있다고 가정).

그리고 전문가의 설명이 정확했습니다. 일반적으로 더 심각한 문제에 대한 반창고 솔루션입니다.

편집 : 나는 확실히 NOLOCK을 사용해야한다고 제안하지 않습니다. 나는 분명히 그것을 분명히 했어야한다고 생각한다. (나는 그것이 괜찮다고 분석 한 극한 상황에서만 그것을 사용할 것입니다). 예를 들어, 얼마 전에 잠금 문제를 완화하기 위해 NOLOCK이 뿌려진 TSQL을 작업했습니다. 나는 그것들을 모두 제거하고 올바른 인덱스를 구현했으며 모든 교착 상태가 사라졌습니다.


3
흠 .. 아직도 이해가 안 돼요. 그래도 괜찮지 만 형체도 형편 없어 .. 그게 무슨 말이야?
Pure.Krome

더티 읽기에 대해 전혀 신경 쓰지 않는다는 가정하에 아프지 않을 것입니다. 하지만 일반적으로 원인이 아닌 증상을 치료하는 경우입니다 ...
Mitch Wheat

2
글쎄요, 저는 그것의 공정한 rexem이 단지 반대표를 받았다고 생각하지 않습니다. 저는 당신이 nolock을 사용할 때 떠오르는 임의의 오류를 해결하지 않았다고 생각합니다. 웹 사이트에서 가끔 빈 오류 페이지를 얻는 것은 좋지 않습니다. 정말 형편없는 형식입니다. 나는 당신이 더러운에 대해주의를 해달라고해도 잘되지 않습니다 읽고 ... "당신이 치료를 해달라고하면 더러운의 벌금을 읽고에 대해"이라는 주장을 싫어하는
샘 사프란

쿼리가 재시도 논리를 구현하지 않은 예외를 생성 할 때 표시되는 빈 페이지입니다. 쿼리 실행 결과 예외가 발생하면 사이트에서 어떤 일이 발생합니까? 모든 곳에서 재시도 논리가 있습니까?
Sam Saffron

적절한 인덱스에 도달하고 있다는 것을 알고있는 매우 잘 최적화 된 쿼리를 사용하십시오. 그런 다음 nolock 힌트를 추가하고 속도가 빨라지는 것을 확인하십시오. 더티 읽기에 신경 쓰지 않으면 nolock을 사용하여 결코 자신을 해치지 않을 것입니다.
Hardwareguy

13

트래픽이 많은 경험이있는 "전문가"는 의심 스럽습니다.

웹 사이트는 일반적으로 사용자가 완전히로드 된 페이지를 볼 때 "더럽습니다". 데이터베이스에서로드 한 다음 편집 된 데이터를 저장하는 양식을 고려해보십시오. 사람들이 더러운 읽기에 대해 그렇게하는 방식은 멍청합니다.

즉, 선택 항목에 여러 레이어를 구축하는 경우 위험한 중복으로 구축 할 수 있습니다. 돈이나 상태 시나리오를 다루는 경우 트랜잭션 데이터 읽기 / 쓰기뿐만 아니라 적절한 동시성 솔루션 (대부분의 "gurus"가 신경 쓰지 않는 것)이 필요합니다.

반면에 웹 사이트에 대한 고급 제품 검색 (예 : 캐시되지 않을 가능성이 높고 약간 집약적 일 가능성이있는 항목)이 있고 동시 사용자가 몇 명 이상인 사이트를 구축 한 적이 있다면 (놀랍게도 "전문가"는 그렇지 않습니다), 그 뒤에있는 다른 모든 프로세스를 병목하는 것은 우스꽝 스럽습니다.

그것이 의미하는 바를 알고 적절할 때 사용하십시오. 오늘날 데이터베이스는 거의 항상 주요 병목이 될 것이며 NOLOCK 사용에 대해 현명하면 인프라에서 수천을 절약 할 수 있습니다.

편집 : 그것은 단지 교착 상태가 아니라 당신이 끝낼 때까지 다른 사람들을 얼마나 기다리게 할 것인지 또는 그 반대의 경우도 마찬가지입니다.

EF4에서 NOLOCK 힌트를 사용하십니까?


10

잘못된 대답은 없지만 약간 혼란 스러울 수 있습니다.

  • 단일 값 / 행을 쿼리 할 때는 항상 NOLOCK을 사용하는 것이 좋지 않습니다. 잘못된 정보를 표시하거나 잘못된 데이터에 대해 조치를 취하지 않을 수도 있습니다.
  • 대략적인 통계 정보를 표시 할 때 NOLOCK은 매우 유용 할 수 있습니다. 예를 들어 SO 가지고 : 읽기 잠금을 취할 말도 안되는 것입니다 정확한 질문이나 태그에 대한 질문의 정확한 수의 전망의 수입니다. 지금은 "sql-server"로 태그가 지정된 3360 개의 질문을 잘못 설명하고 트랜잭션 롤백으로 인해 1 초 후에 3359 개의 질문이 표시되는 경우 아무도 신경 쓰지 않습니다.

나는 당신의 첫 번째 요점에 전혀 동의하지 않습니다. 단일 값 / 행을 쿼리하고 해당 행에 대한 고유 ID를 지정하고 다른 프로세스가 액세스하지 않는다는 것을 알고 있다면 nolock을 사용하는 것이 완벽하게 허용되며 동시 애플리케이션의 차단을 줄입니다.
tuseau

1
아니, 그렇지 않습니다. 다른 이유로 행이 변경 될 수 있습니다. 예를 들어 다른 행을 삽입하면 페이지가 분할됩니다. 적절한 인덱싱, 커밋 된 스냅 샷 읽기 및 스냅 샷 격리는 거의 항상 더 나은 아이디어입니다.
Mark Sowul 2012

1
@tuseau 다른 프로세스가 행에 액세스하지 않는다는 것을 "알면"잠금을 취하는 행위는 아무것도 차단하지 않으므로 비용이 거의 들지 않습니다.
Andrew Hill

2

전문 개발자로서 저는 상황에 따라 다릅니다. 하지만 저는 확실히 GATS와 OMG Ponies의 조언을 따릅니다. 당신이하는 일을 알고, 그것이 언제 도움이되는지, 언제 아프고,

힌트 및 기타 좋지 않은 아이디어 읽기

SQL 서버를 더 깊이 이해하게 만들 수 있습니다. 나는 일반적으로 SQL 힌트가 사악하다는 규칙을 따르지만, 불행히도 가끔씩 SQL 서버를 강제하는 데 지칠 때마다 사용합니다. 그러나 이것은 드문 경우입니다.

루크


2

앱 지원이 SSMS (보고를 통해 제공되지 않음)를 사용하여 프로덕션 서버의 ad-hock 쿼리에 응답하고 싶을 때 nolock을 사용하도록 요청했습니다. 이렇게하면 '주요'사업이 영향을받지 않습니다.


2

나는 NOLOCK 힌트에 대한 일부 의견, 특히 "적절할 때 사용"하는 의견에 동의합니다. 응용 프로그램이 제대로 작성되지 않았고 동시성을 부적절한 방식으로 사용하는 경우 잠금 에스컬레이션이 발생할 수 있습니다. 트랜잭션이 많은 테이블도 특성상 항상 잠기고 있습니다. 인덱스 적용 범위가 좋다고해서 데이터 검색에 도움이되지는 않지만 ISOLATION LEVEL을 READ UNCOMMITTED로 설정하면 도움이됩니다. 또한 NOLOCK 힌트를 사용하는 것이 변경의 성격을 예측할 수있는 많은 경우에 안전하다고 생각합니다. 예를 들어, 여행자가있는 작업이 많은 측정 삽입과 함께 서로 다른 프로세스를 거치는 제조에서 NOLOCK 힌트를 사용하여 완료된 작업에 대해 안전하게 쿼리를 실행할 수 있으며 이렇게하면 테이블에 PROMOTED 또는 EXCLUSIVE 잠금을 설정하는 다른 세션과의 충돌을 방지 할 수 있습니다. /페이지. 이 경우 액세스하는 데이터는 정적이지만 수억 개의 레코드와 분당 수천 개의 업데이트 / 삽입이있는 매우 트랜잭션 테이블에 상주 할 수 있습니다. 건배


2

나는 nolock을 사용하는 것이 사실상 결코 정확하지 않다고 생각합니다.

단일 행을 읽는 경우 올바른 인덱스는 개별 행 작업이 빠르게 완료되므로 NOLOCK이 필요하지 않음을 의미합니다.

임시 표시 이외의 다른 행을 읽고 결과를 반복하거나 생성 된 숫자로 방어하는 데 관심이 있다면 NOLOCK은 적절하지 않습니다.

NOLOCK은 "이 답변에 중복 행, 삭제 된 행 또는 롤백으로 인해 처음에 삽입되지 않은 행이 포함되어 있는지 상관하지 않습니다."에 대한 대리 태그입니다.

NOLOCK에서 가능한 오류 :

  • 일치하는 행은 전혀 반환되지 않습니다.
  • 단일 행이 여러 번 반환 됨 (동일한 기본 키의 여러 인스턴스 포함)
  • 일치하지 않는 행이 반환됩니다.

noLock 선택이 실행되는 동안 페이지 분할을 유발할 수있는 모든 조치로 인해 이러한 일이 발생할 수 있습니다. 거의 모든 작업 (삭제 포함)으로 인해 페이지가 분할 될 수 있습니다.

따라서 실행하는 동안 행이 변경되지 않는다는 것을 "알면"인덱스가 효율적인 검색을 허용하므로 nolock을 사용하지 마십시오.

쿼리가 실행되는 동안 행이 변경 될 수 있다고 의심되고 정확성에 관심이 있다면 nolock을 사용하지 마십시오.

교착 상태로 인해 NOLOCK을 고려하는 경우 예상치 못한 테이블 스캔에 대한 쿼리 계획 구조를 조사하고 교착 상태를 추적하고 발생 이유를 확인하십시오. 쓰기 주변의 NOLOCK은 이전에 교착 상태가 된 쿼리가 잠재적으로 둘 다 잘못된 답변을 작성 함을 의미 할 수 있습니다.


2

가능한 경우 더 나은 솔루션은 다음과 같습니다.

  • 로그 복제를 사용하여 데이터를보고 데이터베이스에 복제합니다.
  • SAN 스냅 샷을 사용하고 일관된 버전의 DB 마운트
  • 더 나은 기본 트랜잭션 격리 수준을 가진 데이터베이스 사용

SNAPSHOT 트랜잭션 격리 수준은 MS가 Oracle에 대한 판매를 잃었 기 때문에 생성되었습니다. Oracle은이 문제를 방지하기 위해 실행 취소 / 다시 실행 로그를 사용합니다. Postgres는 MVCC를 사용합니다. 미래에 MS의 Heckaton은 MVCC를 사용할 것이지만 생산 준비가되기까지는 몇 년이 걸립니다.


위에 오타가 있습니다. "더 나은 기본 트랜잭션 격리 메커니즘"을 의미합니다.
pwy

1
SNAPSHOT 트랜잭션 격리 수준은 MS의 발명품입니다. 기본적으로 TEMPDB의 임시 테이블에 데이터를 넣습니다. 해당 DB는 박스의 모든 DB에서 공유됩니다. 따라서 가능하면 TEMPDB에 SSD를 사용하는 것이 좋습니다. 다른 옵션보다 노력이 적을 것입니다.
pwy

1

NOLOCK은 종종 데이터베이스 읽기 속도를 높이는 마법의 방법으로 악용되지만 가능한 한 사용하지 않으려 고합니다.

결과 집합에는 아직 커밋되지 않았으며 나중에 롤백되는 행이 포함될 수 있습니다.

오류 또는 결과 세트는 비어 있거나 누락 된 행이거나 동일한 행을 여러 번 표시 할 수 있습니다.

다른 트랜잭션이 데이터를 읽는 동시에 데이터를 이동하기 때문입니다.

READ COMMITTED는 여러 사용자가 동시에 동일한 셀을 변경하는 단일 열 내에서 데이터가 손상되는 추가 문제를 추가합니다.


-2

이미 작성된 시스템이 있고 테이블에 인덱스를 추가 한 다음 14gig 데이터 테이블의 데이터로드 속도가 급격히 느려지는 실제 환경에서는 보고서 및 월말 처리에 WITH NOLOCK을 사용하여 집계 기능 (합계 , count 등)은 행, 페이지, 테이블 잠금을 수행하지 않고 전체 성능을 저하시킵니다. 새 시스템에서는 WITH NOLOCK을 사용하지 않고 인덱스를 사용하지 않습니다.하지만 인덱스를 추가하면 데이터로드가 심각하게 저하되고, 제가 지시를 받으면 코드베이스를 변경하여 인덱스를 삭제 한 다음 대량로드 한 다음 인덱스를 다시 만듭니다. 새로운 시스템을 개발하고 있다면 모두 훌륭하고 훌륭합니다. 그러나 이미 시스템이있는 경우에는 그렇지 않습니다.


1
무엇 당신은 말을
최대 알렉산더 한나
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.