[sql-server] UPDLOCK, HOLDLOCK에 대해 혼란 스러움

Table Hints 사용을 조사하는 동안 다음 두 가지 질문을 발견했습니다.

두 질문에 대한 답변은를 사용할 때 (UPDLOCK, HOLDLOCK)다른 프로세스가 해당 테이블의 데이터를 읽을 수 없다고 말하지만 나는 이것을 보지 못했습니다. 테스트를 위해 테이블을 만들고 두 개의 SSMS 창을 시작했습니다. 첫 번째 창에서 다양한 테이블 힌트를 사용하여 테이블에서 선택한 트랜잭션을 실행했습니다. 트랜잭션이 실행되는 동안 두 번째 창에서 차단되는 것을 확인하기 위해 다양한 문을 실행했습니다.

테스트 테이블 :

CREATE TABLE [dbo].[Test](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [Value] [nvarchar](50) NULL,
 CONSTRAINT [PK_Test] PRIMARY KEY CLUSTERED
(
    [ID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

SSMS 창 1 :

BEGIN TRANSACTION

SELECT * FROM dbo.Test WITH (UPDLOCK, HOLDLOCK)
WAITFOR DELAY '00:00:10'

COMMIT TRANSACTION

SSMS 창 2에서 (다음 중 하나 실행) :

SELECT * FROM dbo.Test
INSERT dbo.Test(Value) VALUES ('bar')
UPDATE dbo.Test SET Value = 'baz' WHERE Value = 'bar'
DELETE dbo.Test WHERE Value= 'baz'

Window 2에서 실행되는 문에 대한 다른 테이블 힌트의 영향 :

           (UPDLOCK)       (HOLDLOCK)    (UPDLOCK, HOLDLOCK)    (TABLOCKX)
---------------------------------------------------------------------------
SELECT    not blocked      not blocked       not blocked         blocked
INSERT    not blocked        blocked           blocked           blocked
UPDATE      blocked          blocked           blocked           blocked
DELETE      blocked          blocked           blocked           blocked

그 질문에 주어진 답을 오해했거나 테스트에서 실수를 했습니까? 그렇지 않다면 왜(UPDLOCK, HOLDLOCK)(HOLDLOCK)혼자?


내가 달성하려는 작업에 대한 추가 설명 :

테이블에서 행을 선택하고 처리하는 동안 해당 테이블의 데이터가 수정되는 것을 방지하고 싶습니다. 해당 데이터를 수정하지 않으며 읽기를 허용하고 싶습니다.

이 답변(UPDLOCK, HOLDLOCK) 은 읽기를 차단할 것이라고 분명히 말합니다 (내가 원하는 것이 아님). 이 답변 에 대한 의견 은 HOLDLOCK읽기를 방지 한다는 것을 의미합니다 . 테이블 힌트의 효과를 더 잘 이해하고UPDLOCK 혼자서 내가 원하는 것을 할 수 있는지 확인하기 위해 위의 실험을 수행하여 그 대답과 상반되는 결과를 얻었습니다.

현재 (HOLDLOCK)는 그것이 내가 사용해야 할 것이라고 생각 하지만 실수를했거나 나중에 나를 물기 위해 돌아올 무언가를 간과했을지도 모른다는 우려가 있습니다.



답변

UPDLOCK 블록이 선택하는 이유는 무엇입니까? 잠금 호환성 매트릭스는 명확 쇼 N에서와 S / U와 U / S 경쟁에 대한, 아니 충돌 .

에 관해서는 HOLDLOCK 문서 상태를 힌트 :

HOLDLOCK : SERIALIZABLE과 동일합니다. 자세한 내용은이 항목 뒷부분의 SERIALIZABLE을 참조하십시오.

SERIALIZABLE : … SERIALIZABLE 격리 수준에서 실행되는 트랜잭션과 동일한 의미로 스캔이 수행됩니다.

그리고 트랜잭션 격리 수준의 주제는 무엇 SERIALIZABLE 방법을 설명합니다 :

다른 트랜잭션은 현재 트랜잭션이 완료 될 때까지 현재 트랜잭션에서 읽은 데이터를 수정할 수 없습니다.

다른 트랜잭션은 현재 트랜잭션이 완료 될 때까지 현재 트랜잭션의 문에서 읽은 키 범위에 속하는 키 값이있는 새 행을 삽입 할 수 없습니다.

따라서 표시되는 동작은 제품 설명서에 완벽하게 설명되어 있습니다.

  • UPDLOCK은 동시 SELECT 또는 INSERT를 차단하지 않지만 T1이 선택한 행의 UPDATE 또는 DELETE를 차단합니다.
  • HOLDLOCK은 SERALIZABLE 의미하므로 SELECTS을 허용하지만, 블록 UPDATE 및 T1에 의해 선택된 행의 삭제 뿐만 아니라 T1에 의해 선택되는 범위의 모든 INSERT (전체 테이블이며, 따라서 임의의 인서트).
  • (UPDLOCK, HOLDLOCK) : 위의 경우 외에 차단되는 항목, 즉 T2에서 UPDLOCK을 사용하는 다른 트랜잭션이 실험에 표시되지 않습니다 .
    SELECT * FROM dbo.Test WITH (UPDLOCK) WHERE ...
  • 설명이 필요없는 TABLOCKX

진짜 질문은 당신이 달성하려는 것이 무엇 입니까? 잠금 의미론에 대한 완전한 110 % 이해가없는 잠금 힌트를 가지고 놀면 문제가 발생합니다 …

OP 편집 후 :

테이블에서 행을 선택하고 처리하는 동안 해당 테이블의 데이터가 수정되는 것을 방지하고 싶습니다.

더 높은 트랜잭션 격리 수준 중 하나를 사용해야합니다. REPEATABLE READ는 읽은 데이터가 수정되는 것을 방지합니다. SERIALIZABLE은 읽은 데이터가 수정 되고 새 데이터가 삽입 되는 것을 방지합니다 . 쿼리 힌트를 사용하는 것과 달리 트랜잭션 격리 수준을 사용하는 것이 올바른 방법입니다. Kendra Little은 격리 수준을 설명하는 멋진 포스터를 가지고 있습니다 .


답변

UPDLOCK은 향후 업데이트 문을 위해 select 문 동안 행을 잠 그려는 경우에 사용됩니다. 향후 업데이트는 트랜잭션의 바로 다음 문이 될 수 있습니다.

다른 세션에서는 계속 데이터를 볼 수 있습니다. UPDLOCK 및 / 또는 HOLDLOCK과 호환되지 않는 잠금을 얻을 수 없습니다.

다른 세션이 잠근 행을 변경하지 못하도록하려는 경우 UPDLOCK을 사용합니다. 잠긴 행을 업데이트하거나 삭제하는 기능을 제한합니다.

다른 세션이보고있는 데이터를 변경하지 못하도록하려면 HOLDLOCK을 사용합니다. 잠근 행을 삽입, 업데이트 또는 삭제하는 기능을 제한합니다. 이렇게하면 쿼리를 다시 실행하고 동일한 결과를 볼 수 있습니다.


답변