Sql 서버 잠 금 모니터링 분석 해결 방향
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 인 스 턴 스 에 로그 인하 여 해당 하 는 추적 속성 을 작성 합 니 다.먼저<일반>페이지 입 니 다.다음 그림 입 니 다.여기 서 두 가지 측면 을 주의 하 십시오.첫째,
이 어<이벤트 선택>항목 을 작성 하고
만년 에 자주 사용 되 는 예 를 들 어 정상 적 인 모니터링 여 부 를 검사 하고 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 에서 키 가 있 는 색인 페이지 Index 찾기Page,이 페이지 의 키 줄 인덱스 를 찾 습 니 다key,대 IndexPage 보유 아이 유 자물쇠,준비 대 Indexkey 는 U 자 물 쇠 를 가지 고 있 지만 Index 발견key 는 세 션 2 에 U 자 물 쇠 를 가지 고 있 습 니 다.
그러면 이때 자물쇠 가 생 긴 다.
해결
RID 검색 을 제외 하고 index 에서 데 이 터 를 찾 으 면 이 잠 금 이 발생 하지 않 습 니 다.즉,메 인 키 에 집합 색인 을 다시 만 들 고 원래 의 비 집합 색인 메 인 키 를 버 리 는 것 입 니 다.이렇게 하면 RID 의 U 잠 금 신청 과 보 유 를 제외 하고 X 잠 금 을 업무 가 끝 날 때 까지 유지 하 는 동시에 키 가 있 는 데이터 페이지 를 홈 키 에 따라 수정 하여 RID 조회 줄 의 시간 을 줄 일 수 있 기 때문이다.
수 정 된 실행 계획 은 다음 과 같다.
그 자물쇠 가 석방 을 신청 하 는 절 차 는 다음 과 같다(상세 한 것 은 캡 처 참조).
이상 은 본 고의 모든 내용 입 니 다.본 고의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 도움 이 되 기 를 바 랍 니 다.또한 저 희 를 많이 지지 해 주시 기 바 랍 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
깊이 중첩된 객체를 정확히 일치 검색 - PostgreSQL목차 * 🚀 * 🎯 * 🏁 * 🙏 JSON 객체 예시 따라서 우리의 현재 목표는 "고용주"사용자가 입력한 검색어(이 경우에는 '요리')를 얻고 이 용어와 정확히 일치하는 모든 사용자 프로필을 찾는 것입니다. 즐거운 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.