MSSQL WITH (NOLOCK) 사용 방법

기본적으로 쿼리 옵티마이저는 SQL 문을 실행하면 최적의 실행 방법으로 쿼리를 실행해줍니다. 쉽게 말해 사용자가 대충 쿼리를 던져줘도 내부적으로는 똑똑하게 쿼리를 최적화해서 실행합니다. 그런데 테이블 힌트라는 것을 쓰면 쿼리 옵티마이저의 동작을 명시적으로 제어할 수 있습니다. 테이블 힌트 중 하나가 SQL Server에서 사용하는 WITH (NOLOCK) 입니다.

MSSQL WITH (NOLOCK)

사용 구문

SELECT *
FROM [테이블] WITH (NOLOCK)
WHERE [조건]

 

WITH (NOLOCK) 사용 이유

1. 테이블을 락(lock)하지 않아 쿼리 중에도 사용할 수 있다.

WITH (NOLOCK)은 일반적으로 SELECT 쿼리에 사용되어 해당 쿼리가 공유 락을 얻지 않도록 합니다. 예를 들어, A 테이블을 SELECT 하는 쿼리가 길게 이어지는 동안에도 A 테이블에 데이터를 INSERT 할 수 있습니다.

 

2. 락에 걸린 테이블도 조회할 수 있다.

다른 프로세스에서 테이블에 락을 걸더라도 쿼리를 수행할 수 있습니다. 예를 들어, A 테이블에 대해 트랜잭션이 끝나지 않은 단계에서도 A 테이블을 SELECT 할 수 있습니다. 이는 데드록(deadlock)을 피할 수 있게 합니다.

 

결론적으로 실시간으로 사용되고 있는 테이블에 대해 SELECT 쿼리를 할 때 데이터 INSERT에 영향을 주지 않으면서 데드록을 피하는 방식으로 쿼리할 수 있게 돕습니다.

 

물론 이런 장점이 있는 반면 트랜잭션이 커밋되지 않은 데이터를 읽을 수 있기 때문에 정확하지 않은 데이터를 얻을 수 있는 부작용도 생깁니다.

 

예시)

TestTable이 있습니다.

 

testtable

 

여기에 아래와 같이 트랜잭션을 시작해서 락을 걸어보겠습니다.

BEGIN TRANSACTION
UPDATE TestTable SET Name = 'Charlie' WHERE ID = 1
-- COMMIT 또는 ROLLBACK을 실행하지 않아 트랜잭션이 열린 상태

 

이 상태에서 다른 쿼리 창을 열고 TestTable을 조회하기 위한 SELECT 쿼리를 시도합니다.

SELECT * FROM TestTable

 

이 쿼리는 첫 번째 쿼리 창에서 실행 중인 트랜잭션 때문에 블로킹되어 결과를 반환하지 않고 계속해서 대기합니다.

 

오래 이어지는 쿼리

 

같은 쿼리 창에서 WITH (NOLOCK)을 사용하여 데이터를 조회해보겠습니다.

SELECT * FROM TestTable WITH (NOLOCK)

 

배타적 락에 구애받지 않고 즉시 결과를 반환합니다.

 

즉시 결과 반환

반응형

댓글

Designed by JB FACTORY