다음을 통해 공유


확장 이벤트의 대상

적용 대상: SQL Server Azure SQL Database Azure SQL Managed Instance

이 문서에서는 확장 이벤트 대상을 사용하는 시기와 방법에 대해 설명합니다. 각 대상에 대해 현재 문서에서는 다음을 설명합니다.

  • 이벤트가 보낸 데이터를 수집하고 보고하는 기능
  • 매개 변수가 자체 설명된 경우를 제외한 매개 변수

다음 표에서는 서로 다른 데이터베이스 엔진에서 각 대상 유형의 사용 가능성을 설명합니다.

대상 형식 SQL Server Azure SQL Database Azure SQL Managed Instance
etw_classic_sync_target 없음 아니요
event_counter
event_file
event_stream
histogram
pair_matching 없음 아니요
ring_buffer

필수 조건

이 문서를 최대한 활용하려면 다음 조건을 충족해야 합니다.

매개 변수, 작업, 필드

CREATE EVENT SESSION 문은 확장 이벤트의 핵심입니다. 이 문을 작성하려면 다음이 필요합니다.

  • 세션에 추가하려는 이벤트
  • 선택한 각 이벤트와 연결된 필드
  • 세션에 추가하려는 각 대상과 연결된 매개 변수

시스템 보기에서 이러한 목록을 반환하는 SELECT 문은 다음 문서의 C 섹션에서 복사하여 사용할 수 있습니다.

B2 섹션(T-SQL 관점)에서 실제 CREATE EVENT SESSION 문의 컨텍스트에서 사용되는 매개 변수, 필드 및 작업을 볼 수 있습니다.

etw_classic_sync_target 대상

SQL Server에서 확장 이벤트는 ETW(Windows용 이벤트 추적)와 상호 운용되어 시스템 활동을 모니터링할 수 있습니다. 자세한 내용은 다음을 참조하세요.

이 ETW 대상은 수신하는 데이터를 동기적으로 처리하는 반면, 대부분의 대상은 비동기적으로 처리합니다.

참고 항목

Azure SQL Managed Instance 및 Azure SQL Database는 etw_classic_sync_target 대상을 지원하지 않습니다. 그 대신 Azure Storage에 저장된 Blob이 있는 event_file 대상을 사용하세요.

event_counter 대상

event_counter 대상은 지정된 각 이벤트의 발생 횟수를 계산합니다.

대부분의 다른 대상과 다른 점:

  • event_counter 대상에는 매개 변수가 없습니다.
  • event_counter 대상은 동기적으로 수신하는 데이터를 처리합니다.

event_counter 대상에서 캡처한 출력 예시

package_name   event_name         count
------------   ----------         -----
sqlserver      checkpoint_begin   4

다음은 이전 결과를 반환한 CREATE EVENT SESSION 문입니다. 이 예제에서는 개수가 4에 도달한 후 계산을 중지하기 위해 WHERE 절 조건자에 package0.counter 필드를 사용했습니다.

CREATE EVENT SESSION [event_counter_1]
    ON SERVER
    ADD EVENT sqlserver.checkpoint_begin   -- Test by issuing CHECKPOINT; statements.
    (
        WHERE [package0].[counter] <= 4   -- A predicate filter.
    )
    ADD TARGET package0.event_counter
    WITH
    (
        MAX_MEMORY = 4096 KB,
        MAX_DISPATCH_LATENCY = 3 SECONDS
    );

event_file 대상

event_file 대상은 버퍼에서 디스크 파일 또는 Azure Storage의 Blob에 이벤트 세션 출력을 씁니다.

  • ADD TARGET 절에 filename 매개 변수를 지정합니다. 파일 확장명은 xel이어야 합니다.
  • 선택한 파일 이름은 시스템에서 날짜-시간 기반의 정수(Long)가 추가된 접두사로 사용되며, 그 뒤에 xel 확장명이 붙습니다.

참고 항목

Azure SQL Managed Instance 및 Azure SQL Database는 filename 매개 변수의 값으로 Azure Storage의 Blob만 사용합니다.

SQL Database 또는 SQL Managed Instance에 대한 event_file 코드 예제는 SQL Database의 확장 이벤트에 대한 이벤트 파일 대상 코드를 참조하세요.

event_file 대상을 사용한 CREATE EVENT SESSION

다음은 event_file 대상을 추가하는 ADD TARGET 절이 포함된 CREATE EVENT SESSION의 예시입니다.

CREATE EVENT SESSION [locks_acq_rel_eventfile_22]
    ON SERVER
    ADD EVENT sqlserver.lock_acquired
    (
        SET
            collect_database_name=(1),
            collect_resource_description=(1)
        ACTION (sqlserver.sql_text,sqlserver.transaction_id)
        WHERE
        (
            [database_name]=N'InMemTest2'
            AND
            [object_id]=370100359
        )
    ),
    ADD EVENT sqlserver.lock_released
    (
        SET
            collect_database_name=1,
            collect_resource_description=1
        ACTION(sqlserver.sql_text,sqlserver.transaction_id)
        WHERE
        (
            [database_name]=N'InMemTest2'
            AND
            [object_id]=370100359
        )
    )
    ADD TARGET package0.event_counter,
    ADD TARGET package0.event_file
    (
        SET filename=N'C:\temp\locks_acq_rel_eventfile_22-.xel'
    )
    WITH
    (
        MAX_MEMORY=4096 KB,
        MAX_DISPATCH_LATENCY=10 SECONDS
    );

sys.fn_xe_file_target_read_file() 함수

event_file 대상은 수신한 데이터를 사람이 읽을 수 없는 이진 형식으로 저장합니다. sys.fn_xe_file_target_read_file 함수를 사용하면 xel 파일의 내용을 관계형 행 집합으로 나타낼 수 있습니다.

SQL Server 2016 이상 버전의 경우 다음 예제와 유사한 SELECT 문을 사용합니다.

SELECT f.*
--,CAST(f.event_data AS XML)  AS [Event-Data-Cast-To-XML]  -- Optional
FROM sys.fn_xe_file_target_read_file(
    'C:\temp\locks_acq_rel_eventfile_22-*.xel', NULL, NULL, NULL)  AS f;

SQL Server 2014 버전의 경우 다음 예제와 유사한 SELECT 문을 사용합니다. SQL Server 2014 이후에는 xem 파일이 더 이상 사용되지 않습니다.

SELECT f.*
--,CAST(f.event_data AS XML)  AS [Event-Data-Cast-To-XML]  -- Optional
FROM sys.fn_xe_file_target_read_file(
    'C:\temp\locks_acq_rel_eventfile_22-*.xel', 'C:\temp\metafile.xem', NULL, NULL) AS f;

이러한 두 예제에서 * 와일드카드는 지정된 접두사로 시작하는 모든 xel 파일을 읽는 데 사용됩니다.

Azure SQL Database에서는 xel Blob이 있는 컨테이너에 대해 ReadList 권한이 있는 SAS 토큰이 포함된 데이터베이스 범위 자격 증명을 만든 후 sys.fn_xe_file_target_read_file() 함수를 호출할 수 있습니다.

/*
Create a master key to protect the secret of the credential
*/
IF NOT EXISTS (
    SELECT 1
    FROM sys.symmetric_keys
    WHERE name = '##MS_DatabaseMasterKey##'
)
CREATE MASTER KEY;

/*
(Re-)create a database scoped credential.
The name of the credential must match the URI of the blob container.
*/
IF EXISTS (
    SELECT *
    FROM sys.database_credentials
    WHERE name = 'https://exampleaccount4xe.blob.core.windows.net/extended-events-container'
)
DROP DATABASE SCOPED CREDENTIAL [https://exampleaccount4xe.blob.core.windows.net/extended-events-container];

/*
The secret is the SAS token for the container. The Read and List permissions are set.
*/
CREATE DATABASE SCOPED CREDENTIAL [https://exampleaccount4xe.blob.core.windows.net/extended-events-container]
    WITH IDENTITY = 'SHARED ACCESS SIGNATURE',
        SECRET = 'sp=rl&st=2023-10-09T22:12:54Z&se=2023-10-10T06:12:54Z&spr=https&sv=2022-11-02&sr=c&sig=REDACTED';

/*
Return event session data
*/
SELECT f.*
--,CAST(f.event_data AS XML)  AS [Event-Data-Cast-To-XML]  -- Optional
FROM sys.fn_xe_file_target_read_file('https://exampleaccount4xe.blob.core.windows.net/extended-events-container/event-session-1', DEFAULT, DEFAULT, DEFAULT) AS f;

Azure SQL Managed Instance에서는 xel Blob이 있는 컨테이너에 대해 ReadList 권한이 있는 SAS 토큰이 포함된 서버 자격 증명을 만든 후 sys.fn_xe_file_target_read_file() 함수를 호출할 수 있습니다.

IF NOT EXISTS (
    SELECT 1
    FROM sys.symmetric_keys
    WHERE name = '##MS_DatabaseMasterKey##'
)
CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'REDACTED';

/*
(Re-)create a database scoped credential.
The name of the credential must match the URI of the blob container.
*/
IF EXISTS (
    SELECT *
    FROM sys.credentials
    WHERE name = 'https://exampleaccount4xe.blob.core.windows.net/extended-events-container'
)
DROP CREDENTIAL [https://exampleaccount4xe.blob.core.windows.net/extended-events-container];

/*
The secret is the SAS token for the container. The Read and List permissions are set.
*/
CREATE CREDENTIAL [https://exampleaccount4xe.blob.core.windows.net/extended-events-container]
    WITH IDENTITY = 'SHARED ACCESS SIGNATURE',
        SECRET = 'sp=rl&st=2023-10-09T22:12:54Z&se=2023-10-10T06:12:54Z&spr=https&sv=2022-11-02&sr=c&sig=REDACTED';

/*
Return event session data
*/
SELECT f.*
--,CAST(f.event_data AS XML)  AS [Event-Data-Cast-To-XML]  -- Optional
FROM sys.fn_xe_file_target_read_file('https://exampleaccount4xe.blob.core.windows.net/extended-events-container/event-session-1', DEFAULT, DEFAULT, DEFAULT) AS f;

sys.fn_xe_file_target_read_file()의 첫 번째 인수에 전체 Blob 이름 대신 Blob 이름 접두사를 지정하면 이 함수는 해당 접두사와 일치하는 컨테이너의 모든 Blob에서 데이터를 반환합니다. 이렇게 하면 Azure Storage에서 지원하지 않는 * 와일드카드를 사용하지 않고도 지정된 이벤트 세션의 모든 롤오버 파일에서 데이터를 검색할 수 있습니다.

이전 Azure SQL 예제에서는 event-session-1이라는 세션의 모든 롤오버 파일을 읽기 위해 xel 확장명을 생략했습니다.

event_file 대상에 저장된 데이터

다음은 SQL Server 2016(13.x) 이상 버전에서 sys.fn_xe_file_target_read_file에서 반환된 데이터의 예시입니다.

module_guid                            package_guid                           object_name     event_data                                                                                                                                                                                                                                                                                          file_name                                                      file_offset
-----------                            ------------                           -----------     ----------                                                                                                                                                                                                                                                                                          ---------                                                      -----------
D5149520-6282-11DE-8A39-0800200C9A66   03FDA7D0-91BA-45F8-9875-8B6DD0B8E9F2   lock_acquired   <event name="lock_acquired" package="sqlserver" timestamp="2016-08-07T20:13:35.827Z"><action name="transaction_id" package="sqlserver"><value>39194</value></action><action name="sql_text" package="sqlserver"><value><![CDATA[  select top 1 * from dbo.T_Target;  ]]></value></action></event>   C:\temp\locks_acq_rel_eventfile_22-_0_131150744126230000.xel   11776
D5149520-6282-11DE-8A39-0800200C9A66   03FDA7D0-91BA-45F8-9875-8B6DD0B8E9F2   lock_released   <event name="lock_released" package="sqlserver" timestamp="2016-08-07T20:13:35.832Z"><action name="transaction_id" package="sqlserver"><value>39194</value></action><action name="sql_text" package="sqlserver"><value><![CDATA[  select top 1 * from dbo.T_Target;  ]]></value></action></event>   C:\temp\locks_acq_rel_eventfile_22-_0_131150744126230000.xel   11776

히스토그램 대상

histogram 대상은 다음이 가능합니다.

  • 여러 항목의 발생 횟수를 개별적으로 계산합니다.
  • 다음과 같은 다른 유형의 항목의 발생 횟수를 계산합니다.
    • 이벤트 필드
    • actions

histogram 대상은 동기적으로 수신하는 데이터를 처리합니다.

source_type 매개 변수는 히스토그램 대상을 조정하는 중요 항목입니다.

  • source_type=0: 이벤트 필드에 대한 데이터를 수집합니다.
  • source_type=1: 작업에 대한 데이터를 수집합니다. 기본값입니다.

slots 매개 변수의 기본값은 256입니다. 다른 값을 할당하면 해당 값이 2의 다음 거듭제곱 값으로 반올림됩니다. 예를 들어 slots=59는 64로 반올림됩니다. histogram 대상에 대한 히스토그램 슬롯의 최대 수는 16384입니다.

histogram을 대상으로 사용할 때 때때로 예기치 않은 결과가 나타날 수 있습니다. 일부 이벤트가 예상한 슬롯에 표시되지 않을 수 있고, 다른 슬롯이 예상보다 높은 이벤트 수를 표시할 수 있습니다.

이 문제는 슬롯에 이벤트를 할당할 때 해시 충돌이 발생하는 경우 일어날 수 있습니다. 이 경우는 드물지만 해시 충돌이 발생하면 한 슬롯에서 계산되어야 할 이벤트가 다른 슬롯에서 계산됩니다. 따라서 특정 슬롯의 개수가 0으로 표시된다고 해서 이벤트가 발생하지 않았다고 가정하는 것은 주의해야 합니다.

한 예로 다음 시나리오를 생각해 보겠습니다.

  • 저장 프로시저 실행을 수집하기 위해 histogram을 대상으로 사용하고 object_id를 기준으로 그룹화하여 확장 이벤트 세션을 설정합니다.
  • 저장 프로시저 A를 실행합니다. 그런 다음 저장 프로시저 B를 실행합니다.

해시 함수가 두 저장 프로시저의 object_id에 대해 동일한 값을 반환하면 히스토그램에 저장 프로시저 A가 두 번 실행된 것으로 표시되고, 저장 프로시저 B는 표시되지 않습니다.

고유 값 수가 상대적으로 적은 경우 이 문제를 완화하려면 히스토그램 슬롯의 수를 예상 고유 값의 제곱보다 높게 설정합니다. 예를 들어 histogram 대상의 sourcetable_name 이벤트 필드로 설정되어 있고 데이터베이스에 20개의 테이블이 있는 경우 20*20 = 400이 됩니다. 400보다 큰 2의 다음 거듭제곱은 512이며, 이 예제에서 권장되는 슬롯 수입니다.

작업이 있는 히스토그램 대상

다음 CREATE EVENT SESSION 문의 ADD TARGET ... (SET ...) 절에서는 대상 매개 변수 할당을 source_type=1로 지정합니다. 이는 히스토그램 대상이 작업을 추적한다는 의미입니다.

현재 예제에서 ADD EVENT ... (ACTION ...) 절은 선택할 수 있는 작업을 sqlos.system_thread_id 하나만 제공합니다. ADD TARGET ... (SET ...) 절에서는 source=N'sqlos.system_thread_id' 할당이 표시됩니다.

참고 항목

이벤트 세션당 동일한 형식의 대상을 둘 이상 추가할 수 없습니다. 여기에는 histogram 대상이 포함됩니다. 또한 histogram 대상당 둘 이상의 원본(작업/이벤트 필드)을 사용하는 것도 불가능합니다. 따라서 별도의 histogram 대상에서 추가 작업이나 이벤트 필드를 추적하려면 새 이벤트 세션이 필요합니다.

CREATE EVENT SESSION [histogram_lockacquired]
    ON SERVER
    ADD EVENT sqlserver.lock_acquired
        (
        ACTION
            (
            sqlos.system_thread_id
            )
        )
    ADD TARGET package0.histogram
        (
        SET
            filtering_event_name=N'sqlserver.lock_acquired',
            slots=16,
            source=N'sqlos.system_thread_id',
            source_type=1
        );

다음 데이터가 캡처되었습니다. value 열의 값은 system_thread_id 값입니다. 예를 들어 총 236 잠금 수는 스레드 6540에서 가져왔습니다.

value   count
-----   -----
 6540     236
 9308      91
 9668      74
10144      49
 5244      44
 2396      28

SELECT를 사용하여 사용 가능한 작업 검색

C.3 SELECT 문은 시스템에서 CREATE EVENT SESSION 문이 지정할 수 있는 작업을 찾을 수 있습니다. WHERE 절에서 먼저 o.name LIKE 필터를 관심 있는 작업과 일치하도록 편집합니다.

다음은 C.3 SELECT에서 반환된 샘플 행 집합입니다. system_thread_id 작업은 두 번째 행에 표시됩니다.

Package-Name   Action-Name                 Action-Description
------------   -----------                 ------------------
package0       collect_current_thread_id   Collect the current Windows thread ID
sqlos          system_thread_id            Collect current system thread ID
sqlserver      create_dump_all_threads     Create mini dump including all threads
sqlserver      create_dump_single_thread   Create mini dump for the current thread

이벤트 필드가 있는 히스토그램 대상

다음 예제에서는 source_type=0을 설정합니다. source에 할당된 값은 이벤트 필드입니다.

CREATE EVENT SESSION [histogram_checkpoint_dbid]
    ON SERVER
    ADD EVENT  sqlserver.checkpoint_begin
    ADD TARGET package0.histogram
    (
    SET
        filtering_event_name = N'sqlserver.checkpoint_begin',
        source               = N'database_id',
        source_type          = 0
    );

다음 데이터는 histogram 대상에 의해 캡처되었습니다. 이 데이터는 ID가 5인 데이터베이스에 7개의 checkpoint_begin 이벤트가 발생했음을 보여 줍니다.

value   count
-----   -----
5       7
7       4
6       3

SELECT를 사용하여 선택한 이벤트에서 사용 가능한 필드를 검색합니다.

C.4 SELECT 문은 선택할 수 있는 이벤트 필드를 보여 줍니다. 먼저 선택한 이벤트 이름으로 o.name LIKE 필터를 편집합니다.

다음은 C.4 SELECT에서 반환된 행 집합입니다. 이 행 집합은 database_idcheckpoint_begin 이벤트에서 histogram 대상에 대한 값을 제공할 수 있는 유일한 필드임을 보여 줍니다.

Package-Name   Event-Name         Field-Name   Field-Description
------------   ----------         ----------   -----------------
sqlserver      checkpoint_begin   database_id  NULL
sqlserver      checkpoint_end     database_id  NULL

pair_matching 대상

pair_matching 대상을 사용하면 해당하는 종료 이벤트 없이 발생하는 시작 이벤트를 감지할 수 있습니다. 예를 들어, lock_acquired 이벤트가 발생했지만 이에 상응하는 lock_released 이벤트가 적시에 뒤따라 수행되지 않으면 문제가 될 수 있습니다.

시스템은 시작 이벤트와 종료 이벤트를 자동으로 일치시키지 않습니다. 대신 CREATE EVENT SESSION 문에서 시스템에 해당 일치를 설명해야 합니다. 시작 이벤트와 종료 이벤트가 일치하면 해당 짝은 삭제하고 일치하지 않는 다른 시작 이벤트에 집중합니다.

시작 및 종료 이벤트 쌍에 대해 일치 가능한 필드 찾기

C.4 SELECT를 사용하면 다음 행 집합에 lock_acquired 이벤트에 대한 약 16개의 필드가 표시됩니다. 여기에 표시된 행 집합은 예제에서 일치하는 필드를 표시하기 위해 수동으로 분할되었습니다. duration과 같은 일부 필드의 경우 일치를 시도하는 것은 의미가 없습니다.

Package-Name   Event-Name   Field-Name               Field-Description
------------   ----------   ----------               -----------------
sqlserver   lock_acquired   database_name            NULL
sqlserver   lock_acquired   mode                     NULL
sqlserver   lock_acquired   resource_0               The ID of the locked object, when lock_resource_type is OBJECT.
sqlserver   lock_acquired   resource_1               NULL
sqlserver   lock_acquired   resource_2               The ID of the lock partition, when lock_resource_type is OBJECT, and resource_1 is 0.
sqlserver   lock_acquired   transaction_id           NULL

sqlserver   lock_acquired   associated_object_id     The ID of the object that requested the lock that was acquired.
sqlserver   lock_acquired   database_id              NULL
sqlserver   lock_acquired   duration                 The time (in microseconds) between when the lock was requested and when it was canceled.
sqlserver   lock_acquired   lockspace_nest_id        NULL
sqlserver   lock_acquired   lockspace_sub_id         NULL
sqlserver   lock_acquired   lockspace_workspace_id   NULL
sqlserver   lock_acquired   object_id                The ID of the locked object, when lock_resource_type is OBJECT. For other lock resource types it will be 0
sqlserver   lock_acquired   owner_type               NULL
sqlserver   lock_acquired   resource_description     The description of the lock resource. The description depends on the type of lock. This is the same value as the resource_description column in the sys.dm_tran_locks view.
sqlserver   lock_acquired   resource_type            NULL

pair_matching 대상의 예

다음 CREATE EVENT SESSION 문은 두 개의 이벤트와 두 개의 대상을 지정합니다. pair_matching 대상은 이벤트를 쌍으로 일치시킬 두 개의 필드 집합을 지정합니다. begin_matching_columnsend_matching_columns에 할당된 쉼표로 구분된 필드의 순서는 동일해야 합니다. 쉼표로 구분된 값에서 언급된 필드 사이에는 탭이나 줄 바꿈이 허용되지 않습니다. 공백은 허용됩니다.

결과 범위를 좁히기 위해 먼저 테스트 테이블의 object_id를 찾을 수 있도록 sys.objects에서 선택했습니다. ADD EVENT ... (WHERE ...) 절에 해당 개체 ID 하나에 대한 필터를 추가했습니다.

CREATE EVENT SESSION [pair_matching_lock_a_r_33]
    ON SERVER
    ADD EVENT sqlserver.lock_acquired
    (
        SET
            collect_database_name = 1,
            collect_resource_description = 1
        ACTION (sqlserver.transaction_id)
        WHERE
        (
            [database_name] = 'InMemTest2'
            AND
            [object_id] = 370100359
        )
    ),
    ADD EVENT sqlserver.lock_released
    (
        SET
            collect_database_name = 1,
            collect_resource_description = 1
        ACTION (sqlserver.transaction_id)
        WHERE
        (
            [database_name] = 'InMemTest2'
            AND
            [object_id] = 370100359
        )
    )
    ADD TARGET package0.event_counter,
    ADD TARGET package0.pair_matching
    (
        SET
            begin_event = N'sqlserver.lock_acquired',
            begin_matching_columns =
                N'resource_0, resource_1, resource_2, transaction_id, database_id',
            end_event = N'sqlserver.lock_released',
            end_matching_columns =
                N'resource_0, resource_1, resource_2, transaction_id, database_id',
            respond_to_memory_pressure = 1
    )
    WITH
    (
        MAX_MEMORY = 8192 KB,
        MAX_DISPATCH_LATENCY = 15 SECONDS
    );

이벤트 세션을 테스트하기 위해, 획득한 두 개의 잠금이 의도적으로 해제되지 않도록 했습니다. 다음 T-SQL 단계를 사용하여 이 작업을 수행했습니다.

  1. BEGIN TRANSACTION.
  2. UPDATE MyTable....
  3. 대상을 검사할 때까지 의도적으로 COMMIT TRANSACTION을 실행하지 않습니다.
  4. 테스트 후 나중에 COMMIT TRANSACTION을 실행했습니다.

단순 event_counter 대상은 다음 출력 행을 제공합니다. 52-50=2이므로, 출력을 통해 pair-matching 대상에서 출력을 검사할 때 2개의 쌍을 이루지 않는 lock_acquired 이벤트가 있음을 알려 줍니다.

package_name   event_name      count
------------   ----------      -----
sqlserver      lock_acquired   52
sqlserver      lock_released   50

pair_matching 대상은 다음 출력 행을 제공합니다. event_counter 출력에서 제안한 대로 실제로 두 개의 lock_acquired 행이 표시됩니다. 이러한 행이 표시된다는 것은 사실 이 두 개의 lock_acquired 이벤트가 짝지어지지 않았다는 것을 의미합니다.

package_name   event_name      timestamp                     database_name   duration   mode   object_id   owner_type   resource_0   resource_1   resource_2   resource_description   resource_type   transaction_id
------------   ----------      ---------                     -------------   --------   ----   ---------   ----------   ----------   ----------   ----------   --------------------   -------------   --------------
sqlserver      lock_acquired   2016-08-05 12:45:47.9980000   InMemTest2      0          S      370100359   Transaction  370100359    3            0            [INDEX_OPERATION]      OBJECT          34126
sqlserver      lock_acquired   2016-08-05 12:45:47.9980000   InMemTest2      0          IX     370100359   Transaction  370100359    0            0                                   OBJECT          34126

짝지어지지 않은 lock_acquired 이벤트의 행에는 sqlserver.sql_text 작업에서 제공하는 T-SQL 텍스트가 포함될 수 있습니다. 이는 잠금을 획득한 쿼리를 캡처합니다.

ring_buffer 대상

ring_buffer 대상은 메모리에서 이루어지는 빠르고 간단한 이벤트 수집에만 편리합니다. 이벤트 세션을 중지하면 저장된 출력이 삭제됩니다.

이 섹션에서는 XQuery를 사용하여 링 버퍼 내용의 XML 표현을 보다 읽기 쉬운 관계형 행 집합으로 변환하는 방법도 보여 줍니다.

ring_buffer 대상을 추가할 때 MAX_MEMORY 매개 변수를 1024KB 이하로 설정합니다. 더 큰 값을 사용하면 메모리 사용량이 불필요하게 증가할 수 있습니다.

기본적으로 MAX_MEMORY 대상의 ring_buffer는 SQL Server에서 제한되지 않으며 Azure SQL Database 및 Azure SQL Managed Instance에서 32MB로 제한됩니다.

다음 예와 같이 ring_buffer 대상의 데이터를 XML로 변환하여 사용합니다. 이 변환 과정에서 4MB XML 문서에 맞지 않는 데이터는 모두 생략됩니다. 따라서 더 큰 MAX_MEMORY 값을 사용하거나 이 매개 변수를 기본값으로 두어 링 버퍼에서 더 많은 이벤트를 캡처하더라도 XML 마크업 및 유니코드 문자열의 오버헤드를 고려할 때 XML 문서 크기의 4MB 제한으로 인해 이벤트를 모두 이용하지 못할 수 있습니다.

예를 들어 XML 문서의 truncated 특성이 1로 설정된 경우 XML로 변환하는 동안 링 버퍼의 내용이 생략된다는 것을 알고 있습니다. 다음은 예입니다.

<RingBufferTarget truncated="1" processingTime="0" totalEventsProcessed="284" eventCount="284" droppedCount="0" memoryUsed="64139">

ring_buffer 대상을 사용한 CREATE EVENT SESSION

다음은 ring_buffer 대상을 사용하여 이벤트 세션을 만드는 예제입니다. 이 예제에서는 MAX_MEMORY 매개 변수가 두 번 나타납니다. 한 번은 ring_buffer 대상 메모리를 1024KB로 설정하기 위해, 한 번은 이벤트 세션 버퍼 메모리를 2MB로 설정하기 위해서입니다.

CREATE EVENT SESSION [ring_buffer_lock_acquired_4]
    ON SERVER
    ADD EVENT sqlserver.lock_acquired
    (
        SET collect_resource_description=(1)
        ACTION(sqlserver.database_name)
        WHERE
        (
            [object_id]=(370100359)  -- ID of MyTable
            AND
            sqlserver.database_name='InMemTest2'
        )
    )
    ADD TARGET package0.ring_buffer
    (
        SET MAX_EVENTS_LIMIT = 98,
            MAX_MEMORY = 1024
    )
    WITH
    (
        MAX_MEMORY = 2 MB,
        MAX_DISPATCH_LATENCY = 3 SECONDS
    );

ring_buffer 대상에서 lock_acquired에 대해 수신한 XML 출력

SELECT 문으로 검색하면 링 버퍼의 콘텐츠가 XML 문서로 표시됩니다. 예시가 다음과 같이 표시됩니다. 그러나 간단히 하기 위해 두 개의 <event> 요소를 제외한 모든 요소가 제거되었습니다. 또한 각 <event> 내에서 소수의 <data> 요소도 제거되었습니다.

<RingBufferTarget truncated="0" processingTime="0" totalEventsProcessed="6" eventCount="6" droppedCount="0" memoryUsed="1032">
  <event name="lock_acquired" package="sqlserver" timestamp="2016-08-05T23:59:53.987Z">
    <data name="mode">
      <type name="lock_mode" package="sqlserver"></type>
      <value>1</value>
      <text><![CDATA[SCH_S]]></text>
    </data>
    <data name="transaction_id">
      <type name="int64" package="package0"></type>
      <value>111030</value>
    </data>
    <data name="database_id">
      <type name="uint32" package="package0"></type>
      <value>5</value>
    </data>
    <data name="resource_0">
      <type name="uint32" package="package0"></type>
      <value>370100359</value>
    </data>
    <data name="resource_1">
      <type name="uint32" package="package0"></type>
      <value>0</value>
    </data>
    <data name="resource_2">
      <type name="uint32" package="package0"></type>
      <value>0</value>
    </data>
    <data name="database_name">
      <type name="unicode_string" package="package0"></type>
      <value><![CDATA[]]></value>
    </data>
    <action name="database_name" package="sqlserver">
      <type name="unicode_string" package="package0"></type>
      <value><![CDATA[InMemTest2]]></value>
    </action>
  </event>
  <event name="lock_acquired" package="sqlserver" timestamp="2016-08-05T23:59:56.012Z">
    <data name="mode">
      <type name="lock_mode" package="sqlserver"></type>
      <value>1</value>
      <text><![CDATA[SCH_S]]></text>
    </data>
    <data name="transaction_id">
      <type name="int64" package="package0"></type>
      <value>111039</value>
    </data>
    <data name="database_id">
      <type name="uint32" package="package0"></type>
      <value>5</value>
    </data>
    <data name="resource_0">
      <type name="uint32" package="package0"></type>
      <value>370100359</value>
    </data>
    <data name="resource_1">
      <type name="uint32" package="package0"></type>
      <value>0</value>
    </data>
    <data name="resource_2">
      <type name="uint32" package="package0"></type>
      <value>0</value>
    </data>
    <data name="database_name">
      <type name="unicode_string" package="package0"></type>
      <value><![CDATA[]]></value>
    </data>
    <action name="database_name" package="sqlserver">
      <type name="unicode_string" package="package0"></type>
      <value><![CDATA[InMemTest2]]></value>
    </action>
  </event>
</RingBufferTarget>

이벤트 세션이 활성 상태인 동안 다음 SELECT를 실행하면 이전 XML을 볼 수 있습니다. XML 데이터는 시스템 보기 sys.dm_xe_session_targets에서 검색됩니다.

SELECT CAST(LocksAcquired.TargetXml AS XML) AS RBufXml
INTO #XmlAsTable
FROM (
    SELECT CAST(t.target_data AS XML) AS TargetXml
    FROM sys.dm_xe_session_targets AS t
    INNER JOIN sys.dm_xe_sessions AS s
        ON s.address = t.event_session_address
    WHERE t.target_name = 'ring_buffer'
        AND s.name = 'ring_buffer_lock_acquired_4'
) AS LocksAcquired;

SELECT *
FROM #XmlAsTable;

행 집합으로 XML을 보기 위한 XQuery

이전 XML을 관계형 행 집합으로 보려면 다음 T-SQL을 실행하여 위의 SELECT 문에서 계속 진행합니다. 주석이 추가된 줄은 XQuery의 각 사용법을 설명합니다.

SELECT
    -- (A)
    ObjectLocks.value('(@timestamp)[1]', 'datetime') AS [OccurredDtTm],
    -- (B)
    ObjectLocks.value('(data[@name="mode"]/text)[1]', 'nvarchar(32)') AS [Mode],
    -- (C)
    ObjectLocks.value('(data[@name="transaction_id"]/value)[1]', 'bigint') AS [TxnId],
    -- (D)
    ObjectLocks.value('(action[@name="database_name" and @package="sqlserver"]/value)[1]', 'nvarchar(128)') AS [DatabaseName]
FROM #XmlAsTable
CROSS APPLY
    -- (E)
    TargetDateAsXml.nodes('/RingBufferTarget/event[@name="lock_acquired"]') AS T(ObjectLocks);

이전 SELECT의 XQuery 메모

(A)

  • timestamp= 특성의 값으로, <event> 요소에 있습니다.
  • '(...)[1]' 구문은 XML 데이터 형식 변수 및 열의 .value() XQuery 메서드에 필요한 제한 사항과 마찬가지로 반복당 하나의 값만 반환되도록 합니다.

(B)

  • <data> 요소 내에 있는 <text> 요소의 내부 값으로, name= 특성이 mode와 같습니다.

(C)

  • <data> 요소 내에 있는 <value> 요소의 내부 값으로, name= 특성이 transaction_id와 같습니다.

(D)

  • <event>에는 <action>가 포함됩니다.
  • <action>은 name= 특성이 database_name이고 package= 특성이 sqlserver(package0이 아님)이며 <value> 요소의 내부 값을 가져옵니다.

(E)

  • CROSS APPLYname 특성이 lock_acquired와 동일한 모든 개별 <event> 요소에 대해 처리를 반복하도록 합니다.
  • 이는 이전 FROM 절에서 반환된 XML에 적용됩니다.

XQuery SELECT의 출력

다음은 XQuery를 포함하는 이전 T-SQL에 의해 생성된 행 집합입니다.

OccurredDtTm              Mode    DatabaseName
------------              ----    ------------
2016-08-05 23:59:53.987   SCH_S   InMemTest2
2016-08-05 23:59:56.013   SCH_S   InMemTest2

event_stream 대상

event_stream 대상은 C#과 같은 언어로 작성 된 .NET 프로그램에서만 사용할 수 있습니다. C# 및 기타 .NET 개발자는 Microsoft.SqlServer.XEvents.Linq 네임스페이스의 .NET Framework 클래스를 통해 이벤트 스트림에 액세스할 수 있습니다. 이 대상은 T-SQL에서 사용할 수 없습니다.

event_stream 대상에서 읽을 때 오류 25726(The event data stream was disconnected because there were too many outstanding events. To avoid this error either remove events or actions from your session or add a more restrictive predicate filter to your session.)이 발생하면, 클라이언트가 데이터를 사용할 수 있는 속도보다 더 빠르게 이벤트 스트림이 데이터로 채워졌다는 의미입니다. 이로 인해 데이터베이스 엔진은 데이터베이스 엔진 성능에 영향을 주지 않도록 이벤트 스트림에서 연결을 끊습니다.

XEvent 네임스페이스