2011-12-05 2 views
10

일부 교착 상태에 문제가있어서 question 게시했습니다.SQL Server, 한 행을 삽입하면 전체 테이블이 잠 깁니다.

나는 도움이되고 내 자신을 많이 찾고 있기 때문에 나는 무슨 일이 일어나고 있는지 알았습니다. 잠금 에스컬레이션을 제어하지 않고 교착 상태를 해결하려면 왜 SQL Server가 한 행을 삽입 할 때 전체 테이블을 잠그는 지 이해해야합니다. 내가 트랜잭션이 문을 실행 한 후 내가 해당 세션에 속하는 10,233 행을 얻을 커밋하기 전에 같이 sys.dm_tran_locks를 조회 할 경우

DECLARE 
    @Type1 INT = 11, 
    @Type2 INT = NULL, 
    @Value1 VARCHAR(20) = '0', 
    @Value2 VARCHAR(20) = '0', 
    @Value3 VARCHAR(20) = '0', 
    @Value4 VARCHAR(20) = '0', 
    @Date1 DATETIME = '2011-11-25', 
    @Date2 DATETIME = '2011-11-25', 
    @Value5 NVARCHAR(50) = '', 
    @Value6 NVARCHAR(50) = '', 
    @Type3 INT = NULL, 
    @Value7 VARCHAR(20) = '4', 
    @Type4 INT = 4, 
    @Type5 INT = 15153, 
    @Type6 INT = 3, 
    @Type7 INT = 31, 
    @Type8 INT = 5976, 
    @Type9 INT = 5044, 
    @Guid1 UNIQUEIDENTIFIER = 'a8293471-3hb4-442b-844f-44t92f17n67s', 
    @Value8 VARCHAR(200) = '02jfgg55savolhffr1mkjf45', 
    @value10 INT = 1, 
    @Option2 BIT = 0, 
    @Value9 VARCHAR(20) = null, 
    @Option1 BIT = 0 

insert into dbo.OurTable 
(
    Type1 
    ,Type2 
    ,Value1 
    ,Value2 
    ,Value3 
    ,Value4 
    ,Date1 
    ,Date2 
    ,Value5 
    ,Value6 
    ,Type3 
    ,Value7 
    ,Type4 
    ,Type5 
    ,Type6 
    ,Type7 
    ,Type8 
    ,Type9 
    ,value10 
    ,Col1 
    ,Col2 
    ,Col3 
    ,Col4 
    ,Value8 
    ,Option2 
    ,Value9 
) 
values 
(
    CASE 
     WHEN [dbo].[GetType](@Type1, null) = 6 AND @Option1 = 1 AND [dbo].[GetType](@Type4, 0) <> 1 
     THEN 7 
     ELSE [dbo].[GetType](@Type1, null) 
    END 
    ,[dbo].[GetType](@Type2, null) 
    ,case when @Value1 = 'null' then null else CAST(@Value1 as numeric(18, 6)) end 
    ,case when @Value2 = 'null' then null else CAST(@Value2 as numeric(18, 6)) end 
    ,case when @Value3 = 'null' then null else CAST(@Value3 as numeric(18, 6)) end 
    ,case when @Value4 = 'null' then null else CAST(@Value4 as numeric(18, 6)) end 
    ,[dbo].[GetDate](@Date1, null) 
    ,[dbo].[GetDate](@Date2, null) 
    ,@Value5 
    ,@Value6 
    ,[dbo].[GetType](@Type3, null) 
    ,case when @Value7 = 'null' then null else CAST(@Value7 as numeric(18, 6)) end 
    ,[dbo].[GetType](@Type4, null) 
    ,@Type6 
    ,case when LOWER(@Type7) = 'null' then null else @Type7 end 
    ,@Type5 
    ,@Type9 
    ,@Type8 
    ,@value10 
    ,GETDATE() 
    ,GETDATE() 
    ,[dbo].[GetGuid](@Guid1) 
    ,[dbo].[GetGuid](@Guid1) 
    ,@Value8 
    ,@Option2 
    ,case when @Value9 = 'null' then null else CAST(@Value9 as int) end 
) 

:

여기에 (이름이 바뀐 변수) 내 삽입 문입니다.

SELECT * 
FROM sys.dm_tran_locks l 
WHERE l.resource_type <> 'DATABASE' AND l.request_session_id = 65 

65는 테스트 할 때 내 현재 창의 세션 ID입니다.

또한 테이블 잠금 (내 교착 상태의 원인)을 보면 테이블 OurTable에 X 잠금이 설정되어 있음을 알 수 있습니다.

resource_type resource_associated_entity_id Name resource_lock_partition request_mode request_type request_status 
OBJECT 290100074 OurTable 0 X LOCK GRANT 
OBJECT 290100074 OurTable 1 X LOCK GRANT 
OBJECT 290100074 OurTable 2 X LOCK GRANT 
OBJECT 290100074 OurTable 3 X LOCK GRANT 
OBJECT 290100074 OurTable 4 X LOCK GRANT 
OBJECT 290100074 OurTable 5 X LOCK GRANT 
OBJECT 290100074 OurTable 6 X LOCK GRANT 
OBJECT 290100074 OurTable 7 X LOCK GRANT 
OBJECT 290100074 OurTable 8 X LOCK GRANT 
OBJECT 290100074 OurTable 9 X LOCK GRANT 
OBJECT 290100074 OurTable 10 X LOCK GRANT 
OBJECT 290100074 OurTable 11 X LOCK GRANT 
OBJECT 290100074 OurTable 12 X LOCK GRANT 
OBJECT 290100074 OurTable 13 X LOCK GRANT 
OBJECT 290100074 OurTable 14 X LOCK GRANT 
OBJECT 290100074 OurTable 15 X LOCK GRANT 

는 처음부터 테이블에 배타적 잠금을 요청하면 나는 이것이 인해 lock escalation을 할 경우 모르거나하지 않습니다. 어쨌든 이것은 교착 상태로 인해 문제가됩니다. 16 개 잠금 행이 하나의 테이블에있다

이유 때문에, 왜 테이블에 의도 배타 잠금 (IX)를 요구하지 않습니다되어 lock partitioning.

내 질문이다? 대신 배타적 잠금을 요청합니다. 어떻게 이것을 막을 수 있습니까? 나는 튜닝 어드바이저에서 튜닝 팁을 얻지 못했고, 나는 이미 그것을 시도했다.

편집 OurTable3의 필드를 업데이트하는 OurTable에 삽입 트리거가 있습니다. 그것은 다음과 같습니다

UPDATE OurTable3 SET Date1 = NULL 
    FROM OurTable3 as E 
     JOIN OurTable2 as C on E.Id = C.FKId 
     JOIN OurTable as ETC on ETC.FKId = C.Id 
      AND (ETC.Date2 IS NULL OR CAST(ETC.Date2 AS DATE) > E.Date1) 
      AND ETC.Type1 = 1 

당신이 OurTable 업데이트하지 않습니다 볼 수 있지만 OurTable3 올바른 행을 업데이트하기 위해 OurTable를 조회 할 수있다.

+1

트랜잭션 격리 수준을 보았습니까? http://msdn.microsoft.com/en-us/library/ms173763.aspx – dash

+1

이 모든 함수가'OurTable'을 참조 할 수 있습니까? 당신은 거기에 많은 기능을 실행합니다 ... – JNK

+1

테이블 구조는 무엇입니까 ?? 클러스터링 키가 있습니까? –

답변

10

답변을 찾았습니다. 우리 팀의 개발자로부터 약간의 실수 (나는 항상 다른 모든 사람들을 비난합니다 :-). Martin Smith는 다른 질문에서 ALLOW_ROW_LOCKS 및 ALLOW_PAGE_LOCKS를 확인해야한다고 지적하여 이미 답변을 알고 있었어야합니다. 하지만 그 당시에 우리는 파티션 ID가 인덱스 ID와 관련이 있다고 생각했고 인덱스 만 검사했습니다.

동일한 데이터가있는 새 테이블을 만드는 것이 었습니다. 효과가 없어졌고 새 테이블에 올바른 IX 잠금 만있었습니다. 그런 다음 갑자기 다시 효과가 나타날 때까지 모든 색인을 생성하고 모든 생성 사이를 테스트했습니다.

내가 OurTable에이 인덱스를 발견 ALLOW_ROW_LOCKS = OFF와 함께

CREATE NONCLUSTERED INDEX [IX_OurTable] ON [dbo].[OurTable] 
(
    [Col1] ASC, 
    [Col2] ASC, 
    [Col3] ASC, 
    [Col4] ASC, 
    [Col5] ASC 
) 
INCLUDE ([Col6], 
[Col7], 
[Col8], 
[Col9]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = OFF, ALLOW_PAGE_LOCKS = OFF, FILLFACTOR = 90) ON [PRIMARY] 
GO 

ALLOW_PAGE_LOCKS = OFF 우리가 삽입 또한 선택에이 영향을 미칠 것입니다 분명하다.

이러한 교착 상태 문제를 해결하는 데 정말 도움이 된 Martin에게 감사의 말을 보내 주셔서 감사합니다.

+1

솔루션을 공유해 주셔서 감사합니다. 까다로운 문제인 것 같아서 귀하의 게시물은 다른 이들을 돕다. – jpierson

관련 문제