UPDLOCK, HOLDLOCK에 대해 혼란 스러움


89

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

답변:


102

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은 격리 수준을 설명하는 멋진 포스터를 가지고 있습니다 .


+1, 자세한 답변에 감사드립니다. 내 목표가 무엇인지에 대한 세부 정보를 추가하기 위해 내 질문을 업데이트 할 것입니다.
Jeff Ogata

1
@Remus Rusanu가 올바른 접근 방식이 쿼리 힌트를 사용하는 대신 격리 수준을 사용하는 이유에 대해 자세히 설명해 주시겠습니까? 두 개의 테이블 만 수정하지 못하도록 잠그기 만하면되는 절차가 있고 TABLOCK, HOLDLOCK을 사용하고 있습니다. 실제로 격리 수준으로 변경하고 트랜잭션의 모든 테이블을 잠 가야합니까?
Steve

TABLOCKX에 대한 설명이 필요합니다. :)
niico 2017

참고 : Kendra Little의 블로그 항목 링크는 404를 반환합니다. 링크에서 알 수 있듯이 2011 년 2 월 2 일자 항목을 찾을 수 없습니다.
Bacon Bits

22

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

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

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

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


1
감사합니다.하지만 제 질문에 실제로 답변하지 않은 것 같습니다. 해당 질문에 대한 답변이 (UPDLOCK,HOLDLOCK)블록 읽기 를 설명하는 데 잘못 되었습니까? (UPDLOCK,HOLDLOCK)대신 사용할 이유가 (HOLDLOCK)있습니까?
Jeff Ogata

내 두 번째 진술은 귀하의 질문에 대한 답변입니다. 다른 세션은 여전히 ​​데이터를 읽을 수 있습니다.
Scott Bruns 2011 년

Updlock, Holdlock은 holdlock과 동일하지 않습니다. Updlock, holdlock은 업데이트를 위해 행을 잠그고 트랜잭션을 직렬화합니다. Holdlock 자체는 트랜잭션을 직렬화합니다. 추가 액세스를 위해 선택한 행을 잠그지 않습니다.
Scott Bruns 2011 년

"UPDLOCK은 향후 업데이트 문을 위해 select 문 중에 행을 잠 그려는 경우에 사용됩니다." XLOCK이 언젠가 작동하지 않을 수 있기 때문에 나는 이것을 좋아합니다
Yiping
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.