님 전에이 질문을하고 답을 받았다 : fix your schema and your code. 이 게시물에서 잠금 충돌은 IX 잠금이었고 의도 잠금에 대한 충돌은 테이블 세분화를 나타내는 높은 세분성 잠금을 나타냅니다.잠금 힌트가 필요하지 않습니다. 색인 및 괜찮은 쿼리가 필요합니다. 대답은 간단하다 예를 들어 가지고 다른 질문, Why does row level locking not appear to work correctly in SQL server? : 잠금 테이블 LockName에 클러스터 된 인덱스를 구성 할 필요가있다 : 다른 세션에
begin transaction
update Locks
set Locked=1
output inserted.*
where LockName = 'A';
:
CREATE TABLE [dbo].[Locks](
[LockName] [varchar](50) NOT NULL,
[Locked] [bit] NOT NULL,
CONSTRAINT [PK_Locks] PRIMARY KEY CLUSTERED ([LockName]));
GO
insert into Locks (LockName, Locked) values ('A', 0);
insert into Locks (LockName, Locked) values ('B', 0);
GO
세션 하나에 이렇게 다음을 수행하십시오 :
begin transaction
update Locks
set Locked=1
output inserted.*
where LockName = 'B';
업데이트 충돌, 차단 없음, (잘못된) 힌트 필요 없음, 아무 것도 없습니다. 올바른 스키마 및 쿼리 설계.
여기에서 설명하는 잠금 장치는 이미 존재하며 키 잠금이라고도합니다. SQL Server는 기본적으로 암시 적 모드로 작동합니다. SQL Server가 초당 16000TPC 트랜잭션의 TPC-C 벤치 마크 번호를 게시 할 수 있다고 상상하십니까? 서버에 필요한 모든 병렬 처리 기능이 있으므로 사용 방법을 이해하려면 책 한 권 또는 두권 만 읽으면됩니다. 주제에 관한 많은 문헌이 있습니다. Transaction Processing: Concepts and Techniques으로 시작할 수 있습니다.
업데이트
begin transaction
select lockname from locks where lockname='A'
update Locks Set locked=1 where lockname='A'
이 상관없이 당신이 시도 얼마나 많은/다양한 잠금 힌트 작동하지 않습니다. 출력 구문이 업데이트 된 이유는 다음과 같습니다.
begin transaction
update Locks
Set locked=1
output inserted.*
where lockname='A'
이렇게하면 처음 업데이트 한 다음 업데이트 한 내용을 반환합니다. 이 기술은 당신이 추구하는 의미와 정확히 일치하는 데이터베이스에서 상당히 일반적입니다 : 자원 획득. 사실이 기술은 자원 획득 포스터 하위 요소의 핵심입니다 : 대기열 처리. 큐 단락 OUTPUT Clause을 참조하십시오. 큐에서 당신이 자원의 테이블을 처리 할 수 있고, 각 스레드 처리, 하나를 잡고 그것을 잠그고 시작 : 별도의 세션에서 지금
create table Resources (
id int identity(1,1) not null,
enqueue_time datetime not null default getutcdate(),
is_processing bit not null default 0,
payload xml);
create clustered index cdxResources on Resources
(is_processing, enqueue_time);
go
-- enqueue:
insert into Resources (payload) values ('<do>This</do>');
insert into Resources (payload) values ('<do>That</do>');
insert into Resources (payload) values ('<do>Something</do>');
insert into Resources (payload) values ('<do>Anything</do>');
이 실행 :
--dequeue
begin transaction;
with cte as (
select top(1) *
from Resources with(readpast)
where is_processing = 0
order by enqueue_time)
update cte
set is_processing = 1
output inserted.*;
당신은 볼 수 있습니다 각 세션은 자신의 리소스를 잡아서 잠그고 모든 사람들이 잠근 모든 것을 건너 뜁니다. 이처럼 정확하게 실행되는 시스템에서는 생산중인 시스템에서이 테이블 (웹 서비스 지불 처리 요청) 인 5 백만 개가 넘는 리소스와 100 개의 동시 처리 프로세서 (약 2 초가 소요됨)에서 초당 약 50 개를 대기열에서 제외하고 처리합니다. 처리 할 호출 당). 정크 하드웨어에. 그래서 절대적으로 가능합니다.
여기 대신 Microsoft에 제안 하시겠습니까? –
나는 그것이 지역 사회에서 나온 것이라면 마이크로 소프트가 더 잘 알고 있다고 생각한다. 게다가 나쁜 생각 일 뿐이므로이 문제를 해결하기 위해 왜 다른 방법을 사용해야 하는지를 알고 싶습니다. – Middletone
정확한 진술 :'select * from table (rowlock updlock) where key = value' 큰 테이블 전체를 잠근다. 또는 귀하의 쿼리가 더 복잡하고 전체 테이블이 잠겨 있는지 확인 하시겠습니까? –