SQL Server에서 기본적으로 어떤 이벤트 정보를 얻을 수 있습니까?


60

나는 종종 어떤 일이 일어 났는지, 언제 일어 났는지, 누가 행동을 수행했는지 사람들이 알고 싶어하는 질문을 봅니다. 많은 경우 SQL Server는이 정보를 자체적으로 추적하지 않습니다. 예를 들면 다음과 같습니다.

  • 누가 저장 프로 시저를 마지막으로 실행 dbo.MyProcedure했습니까?
  • 누가 테이블 의 salary열을 업데이트 dbo.Employees했습니까?
  • 누가 dbo.OrdersManagement Studio에서 마지막으로 테이블을 쿼리 했습니까?

그러나 SQL Server 기본적으로 일시적으로 추적 하는 몇 가지 다른 이벤트가 있으며 다음과 같은 기본적으로 질문에 대답 할 수 있습니다.

  • AdventureWorks 데이터베이스에서 자동 증가가 마지막으로 발생한 시간은 언제이며 얼마나 걸립니까?
  • 누가 dbo.EmployeeAuditData테이블을 언제 삭제 했습니까?
  • 오늘 몇 개의 메모리 관련 오류가 발생 했습니까?

이 정보는 어떻게 구할 수 있으며 얼마나 오래 사용할 수 있습니까?

답변:


65

SQL Server가 기본적으로 추적하는 유용한 정보가 많이 있습니다. SQL Server 2005부터 백그라운드에서 실행되는 "기본 추적"이 있었으며 SQL Server 2008부터라는 확장 이벤트 세션이 자동으로 실행되었습니다 system_health.

또한 SQL Server 오류 로그, SQL Server 에이전트 로그, Windows 이벤트 로그 및 SQL Server 감사 , 관리 데이터웨어 하우스 , 이벤트 알림 , DML 트리거 , DDL 트리거 , SCOM / 시스템 센터 등의 추가 로깅에서 특정 정보를 찾을 수 있습니다. , 자신의 서버 측 추적 또는 확장 이벤트 세션 또는 타사 모니터링 솔루션 (예 : 고용주 SQL Sentry에서 만든 것과 같은 ). 선택적 으로 문제 해결을 위해 소위 "블랙 박스 추적"을 활성화 할 수도 있습니다 .

그러나이 게시물에서는 기본 추적, 확장 이벤트 세션 및 오류 로그 등 대부분의 경우 가장 일반적으로 사용되는 항목에 중점을 두겠습니다.

기본 추적

기본 추적은를 사용하여 비활성화sp_configure 하지 않는 한 대부분의 시스템에서 실행됩니다 . 이 기능이 활성화되어 있으면 유용한 정보를 풍부하게 얻을 수 있습니다. 다음은 캡처 된 추적 이벤트를 나열합니다.

DECLARE @TraceID INT;

SELECT @TraceID = id FROM sys.traces WHERE is_default = 1;

SELECT t.EventID, e.name as Event_Description
  FROM sys.fn_trace_geteventinfo(@TraceID) t
  JOIN sys.trace_events e ON t.eventID = e.trace_event_id
  GROUP BY t.EventID, e.name;

sys.trace_columns어떤 이벤트가 어떤 데이터와 함께 제공되는지 알아보기 위해 더 자세하게 알아볼 수 있지만, 실제로는 특정 이벤트에 대한 추적 데이터를 쿼리 할 때 가지고있는 것을 볼 수 있으므로 지금은 생략하겠습니다. 다음은 내 시스템에서 사용할 수있는 이벤트입니다 (SQL Server 2019 CTP 2.4를 통해 동일한 이벤트 세트 임에도 불구하고 쿼리를 실행하여 일치하는지 확인하십시오).

EventID  Event_Description
-------  ----------------------------------------------
18       Audit Server Starts And Stops
20       Audit Login Failed
22       ErrorLog
46       Object:Created
47       Object:Deleted
55       Hash Warning
69       Sort Warnings
79       Missing Column Statistics
80       Missing Join Predicate
81       Server Memory Change
92       Data File Auto Grow
93       Log File Auto Grow
94       Data File Auto Shrink
95       Log File Auto Shrink
102      Audit Database Scope GDR Event
103      Audit Schema Object GDR Event
104      Audit Addlogin Event
105      Audit Login GDR Event
106      Audit Login Change Property Event
108      Audit Add Login to Server Role Event
109      Audit Add DB User Event
110      Audit Add Member to DB Role Event
111      Audit Add Role Event
115      Audit Backup/Restore Event
116      Audit DBCC Event
117      Audit Change Audit Event
152      Audit Change Database Owner
153      Audit Schema Object Take Ownership Event
155      FT:Crawl Started
156      FT:Crawl Stopped
164      Object:Altered
167      Database Mirroring State Change
175      Audit Server Alter Trace Event
218      Plan Guide Unsuccessful

기본 추적은 롤오버 파일을 사용하므로 사용 가능한 데이터는 지금까지만 되돌아갑니다. 사용 가능한 데이터의 날짜 범위는 캡처되는 위의 이벤트 수와 빈도에 따라 다릅니다. 더 긴 히스토리를 유지하려면 추적과 연관된 현재 비활성 파일을 주기적으로 아카이브하는 작업을 설정할 수 있습니다.

질문에서 나는 내가 찾은 몇 가지 질문을했다. 다음은 기본 추적에서 특정 정보를 가져 오는 쿼리 예입니다.

질문 : AdventureWorks 데이터베이스에서 자동 증가가 마지막으로 발생한 시간은 언제이며 얼마나 걸립니까?

이 쿼리는 AdventureWorks 데이터베이스에서 로그 파일과 데이터 파일 모두에 대해 여전히 기본 추적 로그 파일에있는 모든 AutoGrow 이벤트를 가져옵니다.

DECLARE @path NVARCHAR(260);

SELECT 
   @path = REVERSE(SUBSTRING(REVERSE([path]), 
   CHARINDEX(CHAR(92), REVERSE([path])), 260)) + N'log.trc'
FROM    sys.traces
WHERE   is_default = 1;

SELECT 
   DatabaseName,
   [FileName],
   SPID,
   Duration,
   StartTime,
   EndTime,
   FileType = CASE EventClass WHEN 92 THEN 'Data' ELSE 'Log' END
FROM sys.fn_trace_gettable(@path, DEFAULT)
WHERE EventClass IN (92,93)
AND DatabaseName = N'AdventureWorks'
ORDER BY StartTime DESC;

질문 : 누가 dbo.EmployeeAuditData 테이블을 언제 삭제 했습니까?

DROP이라는 객체에 대한 모든 이벤트 가 반환됩니다 EmployeeAuditData. DROP테이블에 대한 이벤트 만 감지 하도록하려면 필터를 추가 할 수 있습니다 ObjectType = 8277( 전체 목록은 여기에 문서화 됨 ). 검색 공간을 특정 데이터베이스로 제한하려는 경우 필터를 추가 할 수 있습니다 DatabaseName = N'db_name'..

DECLARE @path NVARCHAR(260);

SELECT 
   @path = REVERSE(SUBSTRING(REVERSE([path]), 
   CHARINDEX(CHAR(92), REVERSE([path])), 260)) + N'log.trc'
FROM    sys.traces
WHERE   is_default = 1;

SELECT 
  LoginName,
  HostName,
  StartTime,
  ObjectName,
  TextData
FROM sys.fn_trace_gettable(@path, DEFAULT)
WHERE EventClass = 47    -- Object:Deleted
AND EventSubClass = 1
AND ObjectName = N'EmployeeAuditData'
ORDER BY StartTime DESC;

여기에는 합병증이 있으며 매우 중요한 경우이지만 어쨌든 언급하는 것이 현명하다고 생각했습니다. 여러 스키마를 사용하고 여러 스키마에서 동일한 오브젝트 이름을 가질 수있는 경우, 해당 스키마 이름이 아직 존재하지 않는 한이를 알 수 없습니다. UserA가 SchemaB.Tablename을 삭제했을 수있는 외부 사례가 있지만 UserB는 SchemaA.Tablename을 삭제했을 수 있습니다. 기본 추적은 오브젝트 의 스키마 를 추적하지 않으며 ( TextData이 이벤트를 캡처하지도 않음 )ObjectID추적에 포함 된 개체는 개체가 삭제되어 더 이상 존재하지 않기 때문에 직접 일치하는 데 유용하지 않습니다. 이 경우 출력에 해당 열을 포함하면 여전히 존재하는 동일한 이름을 가진 테이블의 모든 사본에 대해 상호 참조하는 것이 유용 할 수 있지만 시스템이 이렇게 많은 혼란에 빠진 경우 (또는 그러한 모든 사본이 삭제 된 경우) 여전히 누가 어떤 테이블의 사본이 삭제되었는지 추측 할 수있는 확실한 방법이 아닐 수도 있습니다.

확장 이벤트

에서 SQL Server 2008을 지원하십시오 system_health 세션 (SQLCSS 블로그) , 다음은 당신이에서 추려 수있는 데이터의 목록입니다 system_healthSQL Server 2008 및 2008 R2에서 세션 :

  • 심각도가> 20 인 오류가 발생한 세션의 sql_text 및 session_id
  • 17803, 701 등과 같은 "메모리"유형의 오류가 발생한 모든 세션에 대한 sql_text 및 session_id
  • "비 수익성"문제에 대한 기록 (오류 로그에서 때때로 메시지 17883으로 표시됨)
  • 감지 된 교착 상태
  • 래치 또는 다른 흥미로운 리소스를 15 초 이상 기다린 세션의 콜 스택, sql_text 및 session_id
  • 30 초 이상 잠금을 대기 한 모든 세션에 대한 콜 스택, sql_text 및 session_id
  • "외부"대기 또는 "선제 대기"동안 오랫동안 대기 한 세션의 콜 스택, sql_text 및 session_id

에서 사용 system_health 이벤트 세션 (MSDN)의 목록은 다소 SQL 서버 2012의 확장 (및 SQL Server 2014에 대한 동일하게 유지)한다 :

  • 심각도가> 20 인 오류가 발생한 세션의 sql_text 및 session_id
  • 메모리 관련 오류가 발생한 세션의 sql_text 및 session_id 오류에는 17803, 701, 802, 8645, 8651, 8657 및 8902가 포함됩니다.
  • 비수익 스케줄러 문제에 대한 기록. (SQL Server 오류 로그에 오류 17883으로 나타납니다.)
  • 감지 된 교착 상태
  • 래치 (또는 기타 흥미로운 리소스)를 15 초 이상 기다린 세션의 콜 스택, sql_text 및 session_id
  • 30 초 이상 동안 잠금을 대기 한 모든 세션에 대한 콜 스택, sql_text 및 session_id
  • 선점 대기를 위해 오랫동안 대기 한 세션에 대한 콜 스택, sql_text 및 session_id 대기 시간은 대기 유형에 따라 다릅니다. 선점 대기는 SQL Server가 외부 API 호출을 기다리는 곳입니다.
  • CLR 할당 및 가상 할당 실패에 대한 콜 스택 및 session_id
  • 메모리 브로커, 스케줄러 모니터, 메모리 노드 OOM, 보안 및 연결에 대한 ring_buffer 이벤트.
  • sp_server_diagnostics의 시스템 구성 요소 결과입니다.
  • scheduler_monitor_system_health_ring_buffer_recorded에 의해 수집 된 인스턴스 상태.
  • CLR 할당 오류
  • connectivity_ring_buffer_recorded를 사용하는 연결 오류
  • security_error_ring_buffer_recorded를 사용하는 보안 오류.

SQL Server 2016에서는 두 가지 이벤트가 더 캡처됩니다.

  • KILL명령을 사용하여 프로세스가 종료 된 경우
  • SQL Server 종료가 시작된 경우

(문서는 아직 업데이트되지 않았지만 이러한 변경 사항 및 기타 변경 사항을 발견하는 방법에 대해 블로그에 올렸습니다 .)

특정 버전에보다 적합한 구성을 적용하려면 항상 다음 쿼리를 직접 실행할 수 있지만 이름을 해석하고 조건을 구문 분석하여 위의보다 자연스러운 언어 목록과 일치시켜야합니다.

SELECT e.package, e.event_id, e.name, e.predicate
  FROM sys.server_event_session_events AS e
  INNER JOIN sys.server_event_sessions AS s
  ON e.event_session_id = s.event_session_id
 WHERE s.name = N'system_health'
 ORDER BY e.package, e.name;

가용성 그룹을 사용하는 경우 실행중인 새 세션이 두 개 있습니다. AlwaysOn_failoverAlwaysOn_health. 다음 쿼리를 통해 수집 한 데이터를 볼 수 있습니다.

SELECT s.name, e.package, e.event_id, e.name, e.predicate
  FROM sys.server_event_session_events AS e
  INNER JOIN sys.server_event_sessions AS s
  ON e.event_session_id = s.event_session_id
 WHERE s.name LIKE N'AlwaysOn[_]%'
 ORDER BY s.name, e.package, e.name;

이러한 이벤트 세션은 링 버퍼 대상을 사용하여 데이터를 저장합니다. 버퍼 풀 및 계획 캐시와 같이 이전 이벤트는 단계적으로 제거되므로 원하는 날짜 범위에서 이벤트를 가져올 수있는 것은 아닙니다.

이 질문에서 나는이 가상의 질문을 제기했습니다.

오늘 몇 개의 메모리 관련 오류가 발생 했습니까?

다음은 system_health세션 에서이 정보를 가져올 수있는 샘플 (아마도 효율적이지 않은) 쿼리입니다 .

;WITH src(x) AS
(
  SELECT y.query('.')
  FROM
  (
    SELECT x = CONVERT(XML, t.target_data)
      FROM sys.dm_xe_sessions AS s
      INNER JOIN sys.dm_xe_session_targets AS t
      ON s.[address] = t.event_session_address
      WHERE s.name = N'system_health'
  ) AS x
  CROSS APPLY x.x.nodes('/RingBufferTarget/event') AS y(y)
)
SELECT 
  x, ts = CONVERT(DATETIME, NULL), err = CONVERT(INT, NULL)
INTO #blat FROM src;

DELETE #blat WHERE x.value('(/event/@name)[1]', 'varchar(255)') <> 'error_reported';

UPDATE #blat SET ts = x.value('(/event/@timestamp)[1]', 'datetime');

UPDATE #blat SET err = x.value('(/event/data/value)[1]', 'int');

SELECT err, number_of_events = COUNT(*)
  FROM #blat
  WHERE err IN (17803, 701, 802, 8645, 8651, 8657, 8902)
  AND ts >= CONVERT(DATE, CURRENT_TIMESTAMP)
  GROUP BY err;

DROP TABLE #blat;

(이 예제 system_health세션 의 Amit Banerjee의 소개 블로그 게시물에서 느슨하게 빌립니다 .)

확장 이벤트 (특정 데이터를 쿼리 할 수있는 많은 예제 포함)에 대한 자세한 내용은 Jonathan Kehayias의 31 부 블로그 시리즈를 참조하십시오.

https://www.sqlskills.com/blogs/jonathan/an-xevent-a-day-31-days-of-extended-events/

오류 기록

SQL Server는 기본적으로 최신 6 개의 최신 오류 로그 파일을 유지하지만 이 값을 변경할 수 있습니다 . 시작 정보 (메모리의 잠금 페이지 설정 여부, 인증 모드 등) 및 시작 정보 (문서의 다른 위치에 캡처 할 수 없을 정도로 심각함) 및 기타 시나리오를 포함하여 많은 정보가 저장됩니다. 최근의 한 예는 데이터베이스가 오프라인 상태가 될 때 찾는 사람이었습니다. 텍스트에 대한 가장 최근의 7 개 오류 로그 각각을 스캔하여이를 확인할 수 있습니다 Setting database option OFFLINE.

EXEC sys.sp_readerrorlog 0,1,'Setting database option OFFLINE';
EXEC sys.sp_readerrorlog 1,1,'Setting database option OFFLINE';
EXEC sys.sp_readerrorlog 2,1,'Setting database option OFFLINE';
EXEC sys.sp_readerrorlog 3,1,'Setting database option OFFLINE';
EXEC sys.sp_readerrorlog 4,1,'Setting database option OFFLINE';
EXEC sys.sp_readerrorlog 5,1,'Setting database option OFFLINE';
EXEC sys.sp_readerrorlog 6,1,'Setting database option OFFLINE';

이 최근 답변에서 다른 세부 사항 다루었 으며 toadworld공식 문서 에도 좋은 배경 정보 있습니다 .

오류 로그가 기본적으로 추적하는 "오류"그룹 중 하나는 모든 성공적인 백업 메시지입니다. 중요한 정보를 훨씬 빨리 떨어 뜨릴 수 있습니다. 추적 플래그 3226활성화 하여 오류 로그에 노이즈가 채워지지 않도록 할 수 있습니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.