[sql-server] SELECT 쿼리에 대한 SQL Server 잠금 이해

SELECT WITH (NOLOCK)테이블에 영향을 미치는 유일한 다른 쿼리가 쿼리 인 경우 테이블 에서 사용하는 이점이 무엇인지 궁금 SELECT합니다.

SQL Server는 어떻게 처리합니까? 겠습니까 SELECT쿼리는 다른 블록 SELECT쿼리를?

저는 SQL Server 2012와 Linq-to-SQL을 사용하고 DataContext있습니다.

(편집하다)

성능 정보 :

  • 잠금을 사용하는 경우 두 번째 SELECT는 첫 번째 SELECT가 완료 될 때까지 기다려야 SELECT합니까?
  • SELECT WITH (NOLOCK)?



답변

SELECTSQL Server의 A 는 테이블 행에 공유 잠금을 설정합니다. 두 번째 SELECT는 공유 잠금이 필요하며 서로 호환됩니다.

따라서 아무도 SELECT다른 사람을 차단할 수 없습니다 SELECT.

어떤 WITH (NOLOCK)쿼리 힌트가 사용되는 것은 (다른 연결에 의해)에 삽입되는 과정에있어 그이 아직 커밋되지 않은 데이터를 읽을 수있다.

해당 쿼리 힌트가 없으면 해당 작업의 트랜잭션이 커밋 (또는 롤백) 될 때까지 행 (또는 전체 테이블)에 배타적 잠금을 설정 SELECT하는 진행중인 INSERT(또는 UPDATE) 문에 의해 테이블 ​​읽기가 차단 될 수 있습니다 .

WITH (NOLOCK)힌트의 문제 는 : 당신이 전혀 삽입되지 않을 데이터 행을 결국 읽을 수 있다는 것입니다 ( INSERT트랜잭션이 롤백 된 경우 )-예를 들어 보고서에 실제로 데이터베이스에 커밋되지 않은 데이터가 표시 될 수 있습니다. .

유용 할 수있는 또 다른 쿼리 힌트가 있습니다 WITH (READPAST). 이것은 SELECT읽기를 시도하고 배타적으로 잠긴 행을 건너 뛰 도록 명령에 지시합니다 . 은 SELECT차단되지 않으며 “더러운”커밋되지 않은 데이터를 읽지 않지만 일부 행을 건너 뛸 수 있습니다 (예 : 테이블의 모든 행을 표시하지 않음).


답변

성능에 대해서는 계속해서 선택에 집중합니다.
Shared는 읽기를 차단하지 않습니다.
공유 잠금 블록 업데이트.
수백 개의 공유 잠금이있는 경우 공유 잠금이 지워질 때까지 기다려야하므로 배타적 잠금을 얻기 위해 잠시 업데이트가 필요합니다.

기본적으로 선택 (읽기)은 공유 잠금을 사용합니다.
공유 (S) 잠금을 사용하면 동시 트랜잭션이 리소스를 읽을 (SELECT) 수 있습니다.
다른 선택에 영향을 미치지 않는 공유 잠금 (1 또는 1000).

차이점은 nolock 대 공유 잠금이 업데이트 또는 삽입 작업에 미치는 영향입니다.

리소스에 공유 (S) 잠금이있는 동안에는 다른 트랜잭션이 데이터를 수정할 수 없습니다.

공유 잠금이 업데이트를 차단합니다!
그러나 nolock은 업데이트를 차단하지 않습니다.

이는 업데이트 성능에 큰 영향을 미칠 수 있습니다. 또한 인서트에 영향을 미칩니다.

더티 읽기 (nolock)는 더럽게 들립니다. 부분적인 데이터를 얻을 수는 없습니다. 업데이트가 John을 Sally로 변경하면 Jolly를 얻을 수 없습니다.

동시성을 위해 공유 잠금을 많이 사용합니다. 데이터를 읽는 즉시 부실합니다. 다음 밀리 초 후에 Sally로 변경되는 John의 읽기는 오래된 데이터입니다. 다음 밀리 초 후에 John이 롤백되는 Sally 읽기는 오래된 데이터입니다. 그것은 밀리 초 수준입니다. 사용자가 공유 잠금을 사용하는 경우 실행하는 데 20 시간이 걸리고 사용자가 잠금을 사용하지 않는 경우 실행하는 데 4 시간이 걸리는 데이터 로더가 있습니다. 이 경우 공유 잠금으로 인해 데이터가 16 시간 유효하지 않게됩니다.

nolocks를 잘못 사용하지 마십시오. 그러나 그들은 장소가 있습니다. 바이트가 1로 설정되어있을 때 체크를 잘라 내고 체크가 끊어 질 때 2로 설정하려면-nolock 시간이 아닙니다.


답변

중요한 코멘트를 추가해야합니다. 모두가 NOLOCK더티 데이터 만 읽는 다고 언급하고 있습니다. 이것은 정확하지 않습니다. 또한 동일한 행을 두 번 얻거나 읽는 동안 전체 행을 건너 뛸 수도 있습니다. 이유는 SQL Server가 b- 트리의 균형을 재조정 할 때 동시에 일부 데이터를 요청할 수 있기 때문입니다.

다른 스레드 확인

https://stackoverflow.com/a/5469238/2108874

http://www.sqlmag.com/article/sql-server/quaere-verum-clustered-index-scans-part-iii.aspx )

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


답변

제 작업에서 우리는 동시에 많은 PC에서 실행되는 매우 큰 시스템을 가지고 있습니다. 매우 큰 테이블에는 수십만 개의 행이 있고 때로는 수백만 개의 행이 있습니다.

매우 큰 테이블에 대해 SELECT를 수행 할 때 사용자가 지난 10 년 동안 수행 한 모든 트랜잭션을 알고 싶어하고 테이블의 기본 키가 효율적인 방식으로 빌드되지 않은 경우 쿼리에 몇 분이 걸릴 수 있습니다. 실행합니다.

그런 다음 우리의 응용 프로그램은 여러 사용자의 PC에서 동시에 실행되어 동일한 데이터베이스에 액세스 할 수 있습니다. 따라서 누군가 다른 SELECT가 읽고있는 테이블에 삽입하려고하면 (SQL이 읽으려고하는 페이지에서) LOCK이 발생하고 두 트랜잭션이 서로를 차단합니다.

우리는 SELECT 문에 “NO LOCK”을 추가해야했습니다. 왜냐하면 많은 사용자가 동시에 많이 사용하는 테이블에 대한 거대한 SELECT 였고 우리는 항상 LOCKS를 가지고 있었기 때문입니다.

내 모범이 충분히 명확한 지 모르겠습니까? 이것은 실제 사례입니다.


답변

SELECT WITH (NOLOCK)수는 필요에 해당 커밋되지 않은 데이터의 읽고 READ UNCOMMITTED데이터베이스에 격리 수준을 설정합니다. NOLOCK키워드는 전체 데이터베이스에서 격리 수준을 설정하는 것보다보다 정밀한 제어 할 수 있습니다.

Wikipedia에는 ​​유용한 기사가 있습니다. Wikipedia : Isolation (데이터베이스 시스템)

다른 stackoverflow 기사에서도 자세히 설명합니다.


답변

잠금없이 선택-삽입되거나 삽입되지 않을 레코드를 선택합니다. 더티 데이터를 읽을 것입니다.

예를 들어 트랜잭션이 1000 개의 행을 삽입 한 다음 실패한다고 가정 해 보겠습니다.

선택하면 1000 개의 행이 표시됩니다.


답변