Sql 서버 잠 금 모니터링 분석 해결 방향

15885 단어 sqlserver자물쇠
배경
1.1 신고 상황
최근 에 필 기 를 정리 해서 모두 EVERNOTE 로 옮 길 계획 입 니 다.자물쇠 라 는 부분 까지 정리 하면 안에 자신 이 기록 한 사례 가 있 습 니 다.다시 정리 해서 공유 해 드 리 겠 습 니 다.
어느 날 정오 경보 문 자 를 받 았 는데 DB 가 이상 하 게 잠 겨 있 었 고 1 분 에 120 개가 잠 겨 있 었 다.
잠 긴 xml 파일 은 다음 과 같 습 니 다:

<deadlock-list>
<deadlock victim="process810b00cf8">
<process-list>
<process id="process810b00cf8" taskpriority="0" logused="0" waitresource="RID: 13:1:1541136:62" waittime="7682" ownerId="3396587959" transactionname="UPDATE" lasttranstarted="2016-01-08T12:03:51.067" XDES="0xa99746d08" lockMode="U" schedulerid="41" kpid="17308" status="suspended" spid="108" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2016-01-08T12:03:51.067" lastbatchcompleted="2016-01-08T12:03:51.067" lastattention="1900-01-01T00:00:00.067" clientapp="Microsoft SQL Server Management Studio -   " hostname="test-server" hostpid="1433" loginname="xinysu" isolationlevel="read committed (2)" xactid="3396587959" currentdb="13" lockTimeout="4294967295" clientoption1="671098976" clientoption2="390200">
<executionStack>
<frame procname="adhoc" line="7" stmtstart="214" stmtend="484" sqlhandle="0x020000003acf4f010561e479685209fb09a7fd15239977c60000000000000000000000000000000000000000">
UPDATE FinanceReceiptNoRule SET NowSeqValue=@ReturnNum,ISRUNNING='0',LastWriteTime=GETDATE() WHERE IsRunning='1' AND SeqCode=@SeqCode </frame>
</executionStack>
<inputbuf>
declare @SeqCode varchar(60)
declare @ReturnNum bigint
set @SeqCode='CGJS20160106'
while(1=1)
begin
UPDATE FinanceReceiptNoRule SET NowSeqValue=@ReturnNum,ISRUNNING='0',LastWriteTime=GETDATE() WHERE IsRunning='1' AND SeqCode=@SeqCode
end </inputbuf>
</process>
<process id="process18fd5d8cf8" taskpriority="0" logused="248" waitresource="KEY: 13:72057594040090624 (b3ade7c5980c)" waittime="4" ownerId="3396522828" transactionname="user_transaction" lasttranstarted="2016-01-08T12:03:05.310" XDES="0x18c1db63a8" lockMode="U" schedulerid="57" kpid="16448" status="suspended" spid="161" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2016-01-08T12:03:58.737" lastbatchcompleted="2016-01-08T12:03:33.847" lastattention="2016-01-08T12:03:33.850" clientapp="Microsoft SQL Server Management Studio -   " hostname="test-server" hostpid="1433" loginname="xinysu" isolationlevel="read committed (2)" xactid="3396522828" currentdb="13" lockTimeout="4294967295" clientoption1="671090784" clientoption2="390200">
<executionStack>
<frame procname="adhoc" line="6" stmtstart="210" stmtend="400" sqlhandle="0x020000001b4f23368af7bba99098c10dec46585804f1b4ce0000000000000000000000000000000000000000">
Update dbo.FinanceReceiptNoRule Set [IsRunning]='1' where SeqCode=@SeqCode and IsRunning='0' </frame>
</executionStack>
<inputbuf>
declare @SeqCode varchar(60)
declare @ReturnNum bigint
set @SeqCode='CGJS20160106'
while(1=1)
begin
Update dbo.FinanceReceiptNoRule Set [IsRunning]='1' where SeqCode=@SeqCode and IsRunning='0' 
end
</inputbuf>
</process>
</process-list>
<resource-list>
<ridlock fileid="1" pageid="1541136" dbid="13" objectname="fin_test.dbo.FinanceReceiptNoRule" id="lock51e8a3980" mode="X" associatedObjectId="72057594040025088">
<owner-list>
<owner id="process18fd5d8cf8" mode="X" />
</owner-list>
<waiter-list>
<waiter id="process810b00cf8" mode="U" requestType="wait" />
</waiter-list>
</ridlock>
<keylock hobtid="72057594040090624" dbid="13" objectname="fin_test.dbo.FinanceReceiptNoRule" indexname="PK_FINANCERECEIPTNORULE" id="lock7b2c6bc80" mode="U" associatedObjectId="72057594040090624">
<owner-list>
<owner id="process810b00cf8" mode="U" />
</owner-list>
<waiter-list>
<waiter id="process18fd5d8cf8" mode="U" requestType="wait" />
</waiter-list>
</keylock>
</resource-list>
</deadlock>
</deadlock-list>
표 구조 와 시 뮬 레이 션 데 이 터 는 다음 과 같다.

--    :
CREATE TABLE [dbo].[FinanceReceiptNoRule](
[SeqCode] [varchar](60) NOT NULL,
[NowSeqValue] [bigint] NULL,
[SeqDate] [varchar](14) NOT NULL,
[IsRunning] [varchar](1) NULL,
[LastWriteTime] [datetime] NULL,
[Prefix] [varchar](4) NULL
) ON [PRIMARY]
GO
--    
INSERT [dbo].[FinanceReceiptNoRule] ([SeqCode], [NowSeqValue], [SeqDate], [IsRunning], [LastWriteTime], [Prefix]) VALUES (N'TEST20150108', 1469, N'20150108', N'0', CAST(N'2015-01-08 05:05:49.163' AS DateTime), N'TEST')
GO
INSERT [dbo].[FinanceReceiptNoRule] ([SeqCode], [NowSeqValue], [SeqDate], [IsRunning], [LastWriteTime], [Prefix]) VALUES (N'TEST20150109', 1377, N'20150109', N'0', CAST(N'2015-01-09 04:50:26.610' AS DateTime), N'TEST')
GO
 
ALTER TABLE [dbo].[FinanceReceiptNoRule] ADD CONSTRAINT [pk_FinanceReceiptNoRule] PRIMARY KEY NONCLUSTERED 
(
[SeqCode] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
1.2 어떻게 모니터링
캡 처 잠 금 은 여러 가지 방법 으로 캡 처 할 수 있 습 니 다.SQL SERVER Profiler 도구 와 Extended Events 를 소개 합 니 다.Profiler 는 상대 적 으로 자원 을 소모 하지만 자물쇠 만 감시 하기 때문에 성능 의 영향 이 크 지 않 고 시각 화 인터페이스 가 손 에 넣 기 쉽다.Extended Events 는 자원 소모 가 적 고 마지막 두 번 째 잠 금 까지 실시 간 으로 기록 하 는 동시에 SQL 문 구 를 분석 하여 기록 파일 을 조회 해 야 합 니 다.
어떻게 Profiler 모니터링 을 사용 합 니까?
SSMS 를 열 고<도구>를 클릭 하고를 선택 하 십시오.다음 그림 입 니 다.

모니터링 이 필요 한 DB 인 스 턴 스 에 로그 인하 여 해당 하 는 추적 속성 을 작성 합 니 다.먼저<일반>페이지 입 니 다.다음 그림 입 니 다.여기 서 두 가지 측면 을 주의 하 십시오.첫째,템 플 릿 을 선택 하 십시오.이 템 플 릿 은 잠 금 을 감시 할 수도 있 고 잠 금 신청 과 방출 상황 을 관찰 할 수도 있 습 니 다.매우 상세 합 니 다.일이 있 으 면 SELECT UPDATE DELETE 등 문 구 를 통 해 잠 금 에 대한 신청 과 방출 상황 을 볼 수 있 습 니 다.둘째,모니터링 결과 저장 은 특정한 표 에 저장 할 수 있 고 정기 적 으로 분석 하고 통계 할 수 있 도록 하 는 것 을 권장 합 니 다.

이 어<이벤트 선택>항목 을 작성 하고Events 만 선택 하면 됩 니 다.다른 것 은 체크 하지 않 아 도 됩 니 다.마지막 으로 실행 을 클릭 하면 모니터링 을 시작 할 수 있 습 니 다.

만년 에 자주 사용 되 는 예 를 들 어 정상 적 인 모니터링 여 부 를 검사 하고 3 개의 조회 창 을 열 수 있 으 며 다음 순서에 따라 실행 하면 자원 점용 과 상호 배척 신청 으로 인해 자물쇠 가 사라 지고 5 단 계 를 수행 하 며 1-3s 를 기다 리 면 생사 자물쇠 가 생 긴 다.스 크 립 트 제공:

--session 1
CREATE TABLE Test_DL(
id int not null primary key ,
name varchar(100));

INSERT INTO Test_DL(id,name) select 1,'a';
INSERT INTO Test_DL(id,name) select 2,'b';

--session2 2 2 2 2 2 2 2 2 2 
BEGIN TRANSACTION
UPDATE Test_DL SET Name='a-test' WHERE ID=1

--session3 3 3 3 3 3 3 3 3 3 
BEGIN TRANSACTION
UPDATE Test_DL SET Name='b-test' WHERE ID=2

--session2 2 2 2 2 2 2 2 2 2 
 SELECT * FROM Test_DL WHERE ID=2

--session3 3 3 3 3 3 3 3 3 3
 SELECT * FROM Test_DL WHERE ID=1

    SQL

감 시 된 잠 금 화면 은 다음 과 같 습 니 다.
 
어떻게 Extended Events 모니터링 을 사용 합 니까?
확장 이벤트 모니터링 을 위 한 스 크 립 트 는 다음 과 같 습 니 다.(확장 이벤트 가 좋 습 니 다.2012 버 전 은 시각 화 작업 을 지원 합 니 다.관심 있 는 것 은 MSDN 에서 알 수 있 습 니 다.https://msdn.microsoft.com/zh-cn/library/bb630282.aspx(본 고 는 문법 등 지식 점 을 분석 하지 않 는 다)

CREATE EVENT SESSION [DeadLock] ON SERVER 
ADD EVENT sqlserver.xml_deadlock_report 
ADD TARGET package0.event_file(SET filename=N'F:\events\deadlock\deadlock.xel',max_file_size=(20)),
ADD TARGET package0.ring_buffer(SET max_events_limit=(100),max_memory=(10240),occurrence_number=(50))
WITH (MAX_MEMORY=4096 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=30 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=NONE,TRACK_CAUSALITY=OFF,STARTUP_STATE=ON)
GO
SQL 을 조회 할 때 다음 과 같 습 니 다.여기 서 주의해 야 할 것 은 버퍼 를 바탕 으로 하 는 지,filer 분석 을 바탕 으로 하 는 지,일반 버퍼 에 저 장 된 개 수 는 모두 유한 합 니 다.예 를 들 어 앞에서 우 리 는 4M 저장 소 만 분 배 했 고 file 분석 은 완전 하지만 보 존 된 파일 개 수 를 봐 야 합 니 다.여기 서 우 리 는 buffer 의 조회 SQL 을 다음 과 같이 보 여 줍 니 다.file 의 조 회 는 여러분 이 관심 이 있 는 것 은 직접 작성 할 수 있 습 니 다.

DECLARE @deadlock_xml XML
SELECT @deadlock_xml=(
      SELECT 
        ( 
        SELECT
          CONVERT(XML, target_data)
        FROM sys.dm_xe_session_targets st
        JOIN sys.dm_xe_sessions s ON s.address = st.event_session_address
        WHERE s.name = 'deadlock' AND st.target_name = 'ring_buffer'
        ) AS [x]
      FOR XML PATH('') , TYPE
      )

SELECT 
dateadd(hour,+6,tb.col.value('@timestamp[1]','varchar(max)')) TimePoint,
tb.col.value('(data/value/deadlock/process-list/process/executionStack/frame)[1]','VARCHAR(MAX)') statement_parameter_k,
tb.col.value('(data/value/deadlock/process-list/process/executionStack/frame)[2]','VARCHAR(MAX)') statement_k,
tb.col.value('(data/value/deadlock/process-list/process/executionStack/frame)[3]','VARCHAR(MAX)') statement_parameter,
tb.col.value('(data/value/deadlock/process-list/process/executionStack/frame)[4]','VARCHAR(MAX)') [statement],
tb.col.value('(data/value/deadlock/process-list/process/@waitresource)[1]','VARCHAR(MAX)') waitresource_k,
tb.col.value('(data/value/deadlock/process-list/process/@waitresource)[2]','VARCHAR(MAX)') waitresource,
tb.col.value('(data/value/deadlock/process-list/process/@isolationlevel)[1]','VARCHAR(MAX)') isolationlevel_k,
tb.col.value('(data/value/deadlock/process-list/process/@isolationlevel)[2]','VARCHAR(MAX)') isolationlevel,
tb.col.value('(data/value/deadlock/process-list/process/@waittime)[1]','VARCHAR(MAX)') waittime_k,
tb.col.value('(data/value/deadlock/process-list/process/@waittime)[2]','VARCHAR(MAX)') waittime,
tb.col.value('(data/value/deadlock/process-list/process/@clientapp)[1]','VARCHAR(MAX)') clientapp_k,
tb.col.value('(data/value/deadlock/process-list/process/@clientapp)[2]','VARCHAR(MAX)') clientapp,
tb.col.value('(data/value/deadlock/process-list/process/@hostname)[1]','VARCHAR(MAX)') hostname_k,
tb.col.value('(data/value/deadlock/process-list/process/@hostname)[2]','VARCHAR(MAX)') hostname
FROM @deadlock_xml.nodes('//event') as tb(col)
이 SQL 은 매우 상세 한 자원 쟁탈 상황 을 조회 할 수 있 습 니 다.확장 이 벤트 를 효과적으로 사용 하려 면 홈 페이지 의 xml 문법(SQL SERVER 가 xml 에 대한 지원 도 훌륭 합 니 다.2016 버 전의 json 지원 을 기대 합 니 다)을 자세히 보 세 요.
 
분명 하지 않 습 니까?한눈 에 알 수 있 습 니 다.이것 만 있 으 면 분석 할 수 있 습 니 다!
2 분석
xml 파일 내용 이나 확장 이벤트 의 모니터링 내용 에 따라 다음 과 같은 정보 로 정리 할 수 있 습 니 다(시작 하 는 잠 금 분석).
 
트 랜 잭 션 1 및 트 랜 잭 션 2 의 실행 계획 을 보 려 면 다음 과 같 습 니 다.
 
표 및 실행 계획 을 결합 하여 잠 금 과정 을 대체적으로 추측 할 수 있 습 니 다.
세 션 1:
  • 키 가 있 는 색인 페이지 를 홈 키 SeqCode 에 따라 찾 습 니 다 IndexPage,이 페이지 위의 keyhashvalue 키 줄 Index 를 찾 습 니 다.key,대 IndexPage 보유 아이 유 자물쇠,대 Indexkey 는 U 자 물 쇠 를 가지 고 있 습 니 다.
  • 이 표 는 쌓 인 표 이기 때문에 bookmark lookup 은 RID 를 통 해 찾 습 니 다.즉,줄 식별 자 를 통 해 RID 에 대응 하 는 줄 데이터 가 있 는 데이터 페이지 를 찾 습 니 다.  Data_Page,그리고 이 페이지 에서 RID 가 가리 키 는 슬롯 번호 의 줄 데 이 터 를 찾 아 이 줄 데이터 에 U 자 물 쇠 를 가지 고 있 습 니 다.
  • 이때 업데이트 할 줄 데 이 터 를 찾 았 습 니 다.데이터 페이지 DataPage 의 IU 자 물 쇠 는 IX 자물쇠 로 업그레이드 되 었 습 니 다.RID 가 가리 키 는 줄 데 이 터 는 U 자물쇠 에서 X 자물쇠 로 업그레이드 되 었 습 니 다.업그레이드 가 끝 난 후 색인 페이지 와 키 줄 위의 IU 자물쇠 와 U 자 물 쇠 를 방출 합 니 다.
  • 이때,세 션 1 은 Data 를 가지 고 있 습 니 다.페이지 의 IX 자물쇠,RID 줄 의 X 자물쇠.
  • 이 과정 에서 마침 세 션 2 에서 이러한 잠 금 신청 을 진행 하 였 습 니 다.
  • 사무 2 에 있 는 자물쇠 자원이 어떤 색인 인지 찾 아 보 세 요.sys.paritions 에 따 르 면 72057594038910976 이 메 인 키 pk 입 니 다.Finance Receipt NoRule,메 인 키 열 은:SeqCode 입 니 다.
  • 키 가 있 는 색인 페이지 를 홈 키 SeqCode 에 따라 찾 습 니 다 IndexPage,이 페이지 의 키 줄 인덱스 를 찾 습 니 다key,대 IndexPage 보유 아이 유 자물쇠,대 Indexkey 는 U 자 물 쇠 를 가지 고 있 습 니 다.
  • 이 표 는 쌓 인 표 이기 때문에 bookmark lookup 은 RID 를 통 해 찾 습 니 다.즉,줄 식별 자 를 통 해 RID 에 대응 하 는 줄 데이터 가 있 는 데이터 페이지 를 찾 습 니 다.  Data_Page,그리고 이 페이지 에서 RID 가 가리 키 는 슬롯 번호 의 줄 데 이 터 를 찾 아 이 줄 데 이 터 를 준비 하여 U 자 물 쇠 를 가지 고 있 지만 RID 줄 에 세 션 1 에 의 해 X 자 물 쇠 를 가지 고 있 는 것 을 발견 하여 U 자물쇠 Timeout 을 신청 합 니 다.
  • 이때 세 션 2 보유 Index페이지 의 아이 유 자물쇠,인덱스key 의 U 자물쇠,Data페이지 의 IU 자물쇠,RID 줄 의 U 자 물 쇠 를 요청 합 니 다.
  • 이 때 를 가정 하면 세 션 1 에서 update 작업 을 한 번 더 실 행 했 습 니 다.(같은 사무 에서)
    홈 키 SeqCode 에서 키 가 있 는 색인 페이지 Index 찾기Page,이 페이지 의 키 줄 인덱스 를 찾 습 니 다key,대 IndexPage 보유 아이 유 자물쇠,준비 대 Indexkey 는 U 자 물 쇠 를 가지 고 있 지만 Index 발견key 는 세 션 2 에 U 자 물 쇠 를 가지 고 있 습 니 다.
    그러면 이때 자물쇠 가 생 긴 다.
  • 세 션 1 보유 DataPage 의 IX 자물쇠,RID 줄 의 X 자물쇠,Index 신청key 의 U 잠 금(세 션 2 방출 대기)
  • 세 션 2 보유 Index페이지 의 아이 유 자물쇠,인덱스key 의 U 자물쇠,Data페이지 의 IU 잠 금,RID 줄 의 U 잠 금 요청(세 션 1 이 풀 릴 때 까지 기다 리 기)
  •  
    해결
    RID 검색 을 제외 하고 index 에서 데 이 터 를 찾 으 면 이 잠 금 이 발생 하지 않 습 니 다.즉,메 인 키 에 집합 색인 을 다시 만 들 고 원래 의 비 집합 색인 메 인 키 를 버 리 는 것 입 니 다.이렇게 하면 RID 의 U 잠 금 신청 과 보 유 를 제외 하고 X 잠 금 을 업무 가 끝 날 때 까지 유지 하 는 동시에 키 가 있 는 데이터 페이지 를 홈 키 에 따라 수정 하여 RID 조회 줄 의 시간 을 줄 일 수 있 기 때문이다.
    수 정 된 실행 계획 은 다음 과 같다.
     
    그 자물쇠 가 석방 을 신청 하 는 절 차 는 다음 과 같다(상세 한 것 은 캡 처 참조).
  • 키 가 있 는 색인 페이지 를 홈 키 SeqCode 에 따라 찾 습 니 다 IndexPage,이 페이지 위의 keyhashvalue 키 줄 Index 를 찾 습 니 다.key,대 IndexPage 보유 아이 유 자물쇠,대 Indexkey 는 U 자 물 쇠 를 가지 고 있 습 니 다.
  • 이 표 는 이미 집합 색인 표 이기 때문에 홈 키 가 있 는 페이지 에 줄 데 이 터 를 포함 하면 IndexPage 보유 한 IU 자 물 쇠 를 IX 자물쇠 로 승급,Indexkey 는 U 자 물 쇠 를 가지 고 X 자물쇠 로 업그레이드 하여 RID 가 줄 마다 데 이 터 를 찾 는 자물쇠 신청 을 피 할 수 있 습 니 다
  •  
    이상 은 본 고의 모든 내용 입 니 다.본 고의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 도움 이 되 기 를 바 랍 니 다.또한 저 희 를 많이 지지 해 주시 기 바 랍 니 다!

    좋은 웹페이지 즐겨찾기