SQL Server에서 "with (nolock)"는 무엇입니까?


610

누군가 with (nolock)가 쿼리를 사용해야하거나 사용하지 않아야 할 때 쿼리 에 사용하는 의미를 설명 할 수 있습니까 ?

예를 들어, 특정 테이블에 높은 트랜잭션 속도와 많은 데이터가 포함 된 뱅킹 애플리케이션이있는 경우 어떤 유형의 쿼리가 문제가되지 않습니까? 항상 사용하거나 사용하지 않아야 할 경우가 있습니까?



1
하나의 링크가 여기에 -mssqltips.com/sqlservertip/2470/…
Steam

답변:


461

WITH (NOLOCK)은 READ UNCOMMITED를 트랜잭션 격리 수준으로 사용하는 것과 같습니다. 따라서 롤백 된 커밋되지 않은 행 (예 : 데이터베이스로 만들지 않은 데이터)을 읽을 위험이 있습니다. 따라서 다른 작업에서 읽기 교착 상태를 방지 할 수는 있지만 위험이 따릅니다. 트랜잭션 속도가 높은 뱅킹 응용 프로그램에서는 IMHO로 해결하려는 모든 문제에 대한 올바른 솔루션이 아닐 수 있습니다.


156
대부분의 뱅킹 애플리케이션은 비즈니스 측면에서 트랜잭션이기 때문에 nolock을 안전하게 사용할 수 있습니다. 새 행만 쓰며 업데이트하지 않습니다.
Jonathan Allen

49
@ Grauenwolf- 삽입되었지만 커밋되지 않은 행은 여전히 ​​더티 판독으로 이어질 수 있습니다.
saasman

16
@ Saasman- 트랜잭션을 롤백하지 않으면 중요하지 않습니다. 또한 삽입 전용 테이블을 사용하면 롤백 가능성이 줄어 듭니다. 그리고 그들이 발생하더라도, 당신은 여전히 ​​말일 분산 보고서에서 모든 것을 고칠 것입니다.
Jonathan Allen

1
나는 확고하다. 추가 된 잠금 힌트가 없다고 가정합니다. 시험 :
Ross Bush

11
NOLOCK와 함께 사용 SELECT하면 선택을 수행하는 동안 데이터가 테이블에 삽입되거나 업데이트되는 경우 동일한 행을 두 번 이상 (중복 된 데이터) 반환 할 위험이 있습니다.
Ian Boyd

170

문제는 더 나쁜 것입니다.

  • 교착 상태 또는
  • 잘못된 가치?

재무 데이터베이스의 경우 교착 상태가 잘못된 값보다 훨씬 나쁩니다. 소리가 거꾸로 들리지만 내 말을들을 수 있습니다. DB 트랜잭션의 전통적인 예는 두 행을 업데이트하여 하나에서 빼고 다른 행에 추가하는 것입니다. 그건 잘못이야

재무 데이터베이스에서는 비즈니스 트랜잭션을 사용합니다. 즉, 각 계정에 하나의 행을 추가해야합니다. 이러한 트랜잭션이 완료되고 행이 성공적으로 작성되는 것이 가장 중요합니다.

계정 잔액을 일시적으로 잘못받는 것은 큰 문제가 아닙니다. 즉, 최종 조정입니다. 그리고 데이터베이스에서 커밋되지 않은 읽기로 인해 두 개의 ATM이 한 번에 사용되므로 계정에서 초과 인출이 발생할 가능성이 훨씬 높습니다.

즉, SQL Server 2005는 NOLOCK필요한 대부분의 버그를 수정했습니다 . 따라서 SQL Server 2000 이전 버전을 사용하지 않는 한 필요하지 않습니다.

추가 읽기
행 수준 버전 관리


22
계정 잔액을 일시적으로 잘못받는 것이 큰 문제가되지 않습니까? 해당 거래가 초과 인출 한도없이 현금 지급기에서 현금을 인출하는 거래 인 경우 어떻게됩니까?
Learning

13
@Learning : 누군가가 카드를 충전하기 30 초 전에 돈을 꺼내면 어떻게됩니까? 모든 의사 소통이 엉망이 될 때까지 초과 인출은 인생의 사실이 될 것입니다.
Jonathan Allen

6
+1 금융 앱 (은행은 물론 모든 곳)에 업데이트 나 삭제가 없습니다. 레코드를 삽입하여 잘못된 조작도 정정됩니다. 이 용어는 영어로 무엇입니까? "storno"입니까? Google은이 질문에 대한 답변을 제공하지 못했습니다
Gennady Vanin Геннадий Ванин

7
늦은 입장 ... 교착 상태를 파악하고 다시 시도해야합니다. 더티 판독 결과
gbn

4
@JonathanAllen은 한마디로, 용어는 최대가 아니라 최대한입니다.
Jimmy D

57

불행히도 커밋되지 않은 데이터를 읽는 것이 아닙니다. 백그라운드에서 페이지를 두 번 읽거나 (페이지가 분할 된 경우) 페이지를 모두 놓칠 수 있습니다. 따라서 결과가 심하게 왜곡 될 수 있습니다.

Itzik Ben-Gan의 기사를 확인 하십시오 . 발췌문은 다음과 같습니다.

"NOLOCK 힌트 (또는 세션의 격리 수준을 READ UNCOMMITTED로 설정)를 사용하면 일관성을 기대하지 않는다고 SQL Server에 알릴 수 있으므로 보장 할 수는 없습니다."일관되지 않은 데이터 "는 나중에 롤백 된 커밋되지 않은 변경 사항이나 트랜잭션의 중간 상태에서 데이터 변경 사항이 표시 될 수도 있습니다. 또한 간단한 쿼리에서 모든 테이블 / 인덱스 데이터를 검색하는 SQL Server가 검색 위치를 잃거나 끝날 수 있음을 의미합니다 같은 행을 두 번 얻는 것 입니다. "


5
조금 더 아래로 같은 행을 두 번 얻는 방법을 설명합니다 . col1의 클러스터형 인덱스가 옵션 IGNORE_DUP_KEY를 사용하여 고유 인덱스로 정의되도록 테이블 T1을 다시 작성하겠습니다. 이는 col1에 중복 값이 ​​존재할 수 없으며 중복 키를 삽입하려고 시도해도 트랜잭션이 실패하지 않고 오류를 생성하는 것이 아니라 경고 만 생성한다는 의미입니다. 이 이상한 옵션을 사용하지 않으면 행을 두 번 얻는 것에 대해 걱정할 필요가 없습니다
JanHudecek

예를 들어 쿼리가 고유하지 않은 인덱스를 사용하는 경우 유선 옵션을 사용하지 않아도 여전히 행 행을 삭제할 수 있습니다. 그러나 이것은 독창적이지 않습니다.
RMD

54

nolock 힌트를 합법적으로 사용하기위한 교과서 예제는 최신 업데이트 OLTP 데이터베이스에 대한 보고서 샘플링입니다.

주제를 예로 들어 보겠습니다. 미국의 한 대형 도로 은행이 은행에서 도시 수준의 첫 번째 징후를 찾는 시간별 보고서를 실행하려는 경우 nolock 쿼리는 도시 당 현금 예금과 현금 인출을 합산 한 거래 테이블을 스캔 할 수 있습니다. 이러한 보고서의 경우 롤백 된 업데이트 트랜잭션으로 인한 작은 비율의 오류로 인해 보고서 값이 줄어들지 않습니다.


31

금융 거래를 데이터베이스 거래로 래핑하지 않는 이유를 확실하지 않습니다 (한 계좌에서 다른 계좌로 자금을 이체 할 때와 같이 한 번에 거래의 한 쪽을 완결하지 않기 때문에 명시 적 거래가 존재하는 이유). 코드가 비즈니스 트랜잭션에서 생각보다 혼란스러워도 모든 트랜잭션 데이터베이스는 오류 또는 실패시 암시 적 롤백을 수행 할 수 있습니다. 나는이 토론이 당신의 머리 위에 있다고 생각합니다.

잠금 문제가있는 경우 버전 관리를 구현하고 코드를 정리하십시오.

잠금은 잘못된 값을 반환 할뿐 아니라 팬텀 레코드와 복제본을 반환합니다.

항상 쿼리 실행 속도를 높이는 것은 일반적인 오해입니다. 테이블에 쓰기 잠금이 없으면 차이가 없습니다. 테이블에 잠금이 있으면 쿼리가 더 빨라질 수 있지만 처음에 잠금이 발명 된 이유가 있습니다.

공평하게, 다음은 nolock 힌트가 유용성을 제공 할 수있는 두 가지 특별한 시나리오입니다.

1) 라이브 OLTP 데이터베이스에 대해 긴 쿼리를 실행해야하는 2005 년 이전 SQL Server 데이터베이스 (유일한 방법 일 수 있음)

2) 기록을 잠그고 UI에 제어권을 반환하는 잘못 작성된 응용 프로그램 및 판독기는 무기한 차단됩니다. 응용 프로그램을 수정할 수없고 (타사 등) 데이터베이스가 2005 년 이전이거나 버전 관리를 켤 수없는 경우 Nolock이 도움이 될 수 있습니다.


11
NOLOCK은 잘못 작성된 코드를 보완하는 데 사용해서는 안된다는 데 동의합니다. 그러나 Johnathan에 대한 공격은 실제로 데이터베이스 트랜잭션을 언급하지 않았으므로 보증하지 않습니다 . 그는 재무 응용 프로그램이 일반적으로 레코드 편집을 허용하지 않는다고 지적했습니다 (분명히 예외가 있음). 귀하의 자금 이체 예에서, 그는 원장에 직불 / 신용 항목을 추가 하는 대신 계정 잔액의 가치 를 변경 하면 이상 할 것이라고 말합니다 .
chrnola

19
다른 은행의 한 계좌에서 다른 계좌로 자금이 이체 될 때 어떻게 생각하십니까? 일부 uber 데이터베이스는 Bank of America의 테이블과 Wells Fargo의 테이블을 잠그고 있습니까? 아니요. 금융 거래는 각각에 기록 된 다음 모든 프로세스가 일치하는지 최종 프로세스를 확인합니다.
Jonathan Allen

24

NOLOCK상당이다 READ UNCOMMITTED, 그러나 마이크로 소프트는 당신이 그것을 사용하지 말아야 말한다 UPDATE또는 DELETE문 :

UPDATE 또는 DELETE 문의 경우 :이 기능은 이후 버전의 Microsoft SQL Server에서 제거됩니다. 새로운 개발 작업에서이 기능을 사용하지 말고 현재이 기능을 사용하는 응용 프로그램을 수정하십시오.

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

이 문서는 SQL Server 2005에 적용되므로 NOLOCK해당 버전을 사용하는 경우 지원 이 제공됩니다. 미래를 보장하기 위해 (더티 읽기를 사용하기로 결정했다고 가정) 코드를 저장 프로 시저에서 사용할 수 있습니다.

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED


21

데이터를 읽을 때만 사용할 수 있으며 아직 커밋되지 않은 데이터를 다시 가져올 지 여부는 신경 쓰지 않습니다.

읽기 작업에서 더 빠를 수는 있지만 실제로 얼마나 말할 수는 없습니다.

일반적으로 사용하지 않는 것이 좋습니다. 커밋되지 않은 데이터를 읽는 것은 약간 혼란 스러울 수 있습니다.


1
SQL Server 2005에 행 버전 관리 기능이 있으므로 잠금이 더 이상 필요하지 않다는 사실을 언급하면 ​​좋을 것입니다.
Jonathan Allen

"with (nolock)"은 여전히 ​​SQL Server 2005에서도 그 자리를 차지하고 있지만 이점은 점점 더 얇아지고 있습니다.
marc_s

18

일반적으로 괜찮은 또 다른 경우는 데이터가 이미 오래되고 쓰기가 발생하지 않는보고 데이터베이스에 있습니다. 그러나이 경우 기본 격리 수준을 변경하여 관리자가 데이터베이스 또는 테이블 수준에서 옵션을 설정해야합니다.

일반적인 경우 : 당신이 때 당신은 그것을 사용할 수 있습니다 매우 확실이 이전 데이터를 읽을 괜찮아있다. 기억해야 할 중요한 점 은 잘못 이해하기가 매우 쉽다는 것 입니다. 예를 들어, 쿼리를 작성할 당시에는 문제가 없더라도 앞으로 이러한 업데이트를 더욱 중요하게 만들기 위해 데이터베이스에 어떤 변화가 없을 것입니까?

나는 아마 그것이 아마 뱅킹 앱에는 좋지 않다는 . 또는 재고 앱. 또는 거래에 대해 생각하고있는 어느 곳에서나.


4
뱅킹 응용 프로그램에서 일하는 사람으로서 나는 자물쇠가 문제가되지 않는다고 말해야합니다. 삽입되었지만 업데이트되거나 삭제되지 않은 행인 트랜잭션 레코드는 커밋되지 않은 데이터를 읽는 문제에 놀랍습니다.
Jonathan Allen

15

간단한 대답-SQL이 데이터를 변경하지 않고 잠금을 통해 다른 활동을 방해 할 수있는 쿼리가있을 때마다.

특히 쿼리에 1 초 이상 걸리는 경우 보고서에 사용되는 모든 쿼리를 고려해야합니다.

OLTP 데이터베이스에 대해 실행중인 OLAP 유형 보고서가있는 경우 특히 유용합니다.

그러나 가장 먼저해야 할 질문은 "왜 이것에 대해 걱정하고 있습니까?"입니다. 내 경험에 따르면 누군가가 "뭔가 시도"모드에있을 때 기본 잠금 동작을 푸는 것이 종종 발생하며 예기치 않은 결과가 발생하지 않는 경우입니다. 너무 이른 경우는 너무 이른 최적화의 경우이고 "경우에 따라"애플리케이션에 너무 쉽게 내장 될 수 있습니다. 왜하고 있는지, 어떤 문제가 해결되는지, 실제로 문제가 있는지 이해하는 것이 중요합니다.


11

짧은 답변:

WITH (NOLOCK)클러스터형 인덱스가있는 테이블의 SELECT 문 에서만 사용하십시오 .

긴 대답 :

WITH (NOLOCK)은 종종 데이터베이스 읽기 속도를 높이는 마법의 방법으로 악용됩니다.

결과 세트에는 아직 커미트되지 않은 행이 포함되어있을 수 있으며이 행은 종종 나중에 롤백됩니다.

비 클러스터형 인덱스가있는 테이블에 WITH (NOLOCK)을 적용하면 행 데이터가 결과 테이블로 스트리밍되므로 다른 트랜잭션에서 행 인덱스를 변경할 수 있습니다. 이는 결과 집합에 행이 누락되거나 동일한 행이 여러 번 표시 될 수 있음을 의미합니다.

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


2
최종 결정을 변경하지 않으면 커밋되지 않은 데이터를 읽을 수 있습니다. 예를 들어, 향후 6 개월 동안 소매점에서 얼마의 돈을 벌려고하는지 Tammy가 실제로 3 개를 샀을 때 종이 타월 2 개를 샀다는 사실은 미래에 대한 당신의 의견을 바꾸지 않을 것입니다 .
Jonathan Allen

1
필터에 지금 포함 된 경우 쿼리를 실행하는 순간 데이터가 정확하지 않습니다. 필터에 기록 데이터 만 포함 된 경우에도 데이터에 READ UNCOMITTED 영향을 미치지 않습니다. 그것이 ANSI 표준에 포함 된 이유가 있습니다.
Jonathan Allen

2
절대 말하지 마 데이터가 100 % 정확해야하는 경우 nolock을 사용하면 안됩니다. 나에게 이것은 일반적으로 그렇지 않다. 사용자에게 데이터를 제시 할 때, 데이터를 처리 할 때까지 데이터는 이미 변경되었지만 변경되지 않았으며 잠금 경합은 응답 지연의 가치가 없습니다.
Perposterer

존재하는 시스템에 충실합시다. 태미는 완벽하게 괜찮은 두뇌를 가지고 있다는 것을 잊지 마십시오. 데이터베이스를 사용하여 아무도주의를 기울이지 않는 작은 종이 타월 구매를 기록하는 것은 전혀 터무니없는 일입니다. 우리의 초점은 사람들이 제 시간에 돈을받는 것, 비상 사태에 대응하는 것 등과 같이 실제로 중요한 시스템입니다. WITH (NOLOCK)의 사용은 존재하는 가치가있는 시스템을 프로그래밍하는 사람들에 의해 이해되는 것이 큰 이점입니다. 사람이 데이터베이스보다 더 나은 작업을 수행 할 수 있으면 해당 자원을 재활용하는 것을 고려하십시오.
WonderWorker

10

내 2 센트- WITH (NOLOCK보고서를 생성해야 할 때 사용하는 것이 좋습니다 . 이 시점에서 데이터는 많이 변경되지 않으며 해당 레코드를 잠그고 싶지 않습니다.


2
현재 변경 사항에 신경 쓰지 않으면 WITH (NoLOCK)이 더 좋습니다.
Abdul Saboor

9

금융 거래를 처리하는 경우 절대 사용하지 않을 것 nolock입니다. nolock업데이트가 많은 대형 테이블에서 선택하는 것이 가장 좋으며 레코드가 오래된 것일 수도 있습니다.

재무 기록 (및 대부분의 응용 프로그램에서 거의 모든 다른 기록)의 nolock경우 기록중인 레코드에서 데이터를 다시 읽을 수 있고 올바른 데이터를 얻지 못할 수 있으므로 혼란에 빠질 수 있습니다.


5
놀랍게도 재무 데이터로 작업 할 때 이것은 문제가되지 않습니다. 하루가 끝날 때 행이 편집되지 않고 계정이 조정되므로 일시적으로 가짜 데이터를 읽는 것은 아무 작업도 수행하지 않습니다.
Jonathan Allen

8

할 일에 대한 "다음 배치"를 검색하는 데 사용했습니다. 이 경우 정확한 항목은 중요하지 않으며 동일한 쿼리를 실행하는 많은 사용자가 있습니다.


1
우리는 할 일이 많은 백그라운드 작업을 제시하는 것과 비슷한 일을합니다. 특정 레코드에 도달 할 때 더 이상 존재하지 않거나 선택 기준과 일치하면 다음 레코드로 넘어갑니다.
TripeHound

7

"더러운"데이터에 문제가 없으면 nolock을 사용하십시오. 이는 nolock이 수정 및 / 또는 커밋되지 않은 데이터를 처리하는 데이터를 읽을 수도 있음을 의미합니다.

트랜잭션이 많은 환경에서 사용하는 것은 일반적으로 좋은 생각이 아니므로 쿼리의 기본 옵션이 아닙니다.


3
필요한 유일한 시간은 트랜잭션이 많은 환경입니다. 테이블이 대부분 유휴 상태이면 아무것도 얻지 못합니다.
Jonathan Allen

7

특히 활동이 많은 SQL Server 2000 데이터베이스에서 (nolock) 힌트를 사용합니다. 그러나 SQL Server 2005에 필요한지 확실하지 않습니다. 최근에 클라이언트의 DBA 요청에 따라 SQL Server 2000에이 힌트를 추가했습니다. 왜냐하면 그는 많은 SPID 레코드 잠금을 알아 채기 때문입니다.

내가 말할 수있는 것은 힌트를 사용하는 것이 우리를 해치지 않았고 잠금 문제를 스스로 해결 한 것으로 보입니다. 해당 고객의 DBA는 기본적으로 우리가 힌트를 사용한다고 주장했습니다.

그건 그렇고, 내가 다루는 데이터베이스는 엔터프라이즈 의료 청구 시스템의 백엔드이므로 많은 조인에서 수백만 건의 레코드와 20 개 이상의 테이블에 대해 이야기하고 있습니다. 나는 일반적으로 조인의 각 테이블에 WITH (nolock) 힌트를 추가합니다 (파생 테이블이 아닌 경우 특정 힌트를 사용할 수 없음)


1
SQL Server 2005에는 "행 버전 관리"가 추가되어 잠금의 필요성이 크게 줄어 듭니다. 우리는 최근에 업그레이드를했으며 DBA의 사용을 중단하도록 교육하지 않고 있습니다.
Jonathan Allen

5

가장 간단한 대답은 간단한 질문입니다. 결과를 반복 할 수 있어야합니까? 그렇다면 NOLOCKS는 어떤 상황에서도 적합하지 않습니다.

반복성이 필요하지 않은 경우 특히 대상 데이터베이스에 연결하는 모든 프로세스를 제어 할 수없는 경우 nolocks가 유용 할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.