Destinos de Eventos extendidos

Se aplica a: SQL Server Azure SQL Database Azure SQL Managed Instance

En este artículo se explica cuándo y cómo usar los destinos de Eventos extendidos. Para cada destino, en el presente artículo se explican:

  • Sus capacidades de recopilar y comunicar los datos enviados por eventos
  • Sus parámetros, excepto cuando el parámetro se explica por sí mismo

En la tabla siguiente se describe la disponibilidad de cada tipo de destino en distintos motores de base de datos.

Tipo de destino SQL Server Azure SQL Database Instancia administrada de Azure SQL
etw_classic_sync_target No No
event_counter
event_file
event_stream
histogram
pair_matching No No
ring_buffer

Requisitos previos

Para aprovechar al máximo este artículo, debes hacer lo siguiente:

Parámetros, acciones y campos

La instrucción CREATE EVENT SESSION es fundamental para los Eventos extendidos. Para escribir la instrucción, necesitas lo siguiente:

  • Los eventos que deseas agregar a la sesión
  • Los campos asociados a cada evento elegido
  • Los parámetros asociados a cada destino que desea agregar a las sesiones

Las instrucciones SELECT que devuelven dichas listas de las vistas del sistema están disponibles para copiarse desde el siguiente artículo, en su sección C:

Puedes ver parámetros, campos y acciones usados en el contexto de una instrucción CREATE EVENT SESSION real, desde la sección B2 (perspectiva de T-SQL).

Destino etw_classic_sync_target

En SQL Server, los Eventos extendidos pueden interoperar con Seguimiento de eventos para Windows (ETW) a fin de supervisar la actividad del sistema. Para más información, vea:

Este destino ETW procesa de forma sincrónica los datos que recibe, mientras que la mayoría de los destinos los procesan de forma asincrónica.

Nota:

Azure SQL Managed Instance y Azure SQL Database no son compatibles con el destino etw_classic_sync_target. Como alternativa, usa el destino event_file con blobs almacenados en Azure Storage.

Destino event_counter

El destino event_counter cuenta cuántas veces se produce cada evento especificado.

A diferencia de la mayoría de los demás destinos:

  • El destino event_counter no tiene parámetros.
  • El destino event_counter procesa los datos que recibe de forma sincrónica.

Salida de ejemplo capturada por el destino event_counter

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

A continuación, se muestra la instrucción CREATE EVENT SESSION que devolvió los resultados anteriores. En este ejemplo, el campo package0.counter se usó en el predicado de cláusula WHERE para detener el recuento después de que el recuento alcance 4.

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 target

El destino event_file escribe la salida de la sesión de eventos del búfer en un archivo de disco o en un blob de Azure Storage:

  • Especifica el parámetro filename en la cláusula ADD TARGET. La extensión del nombre de archivo debe ser xel.
  • El sistema usa el nombre de archivo que elige como prefijo al que se anexa un entero largo basado en fecha y hora, seguido de la extensión xel.

Nota:

Azure SQL Managed Instance y Azure SQL Database solo blobs en Azure Storage como valor del parámetro filename.

Para ver un ejemplo de código de event_file para SQL Database o SQL Managed Instance, consulta Código de destino del archivo de evento para Eventos extendidos en SQL Database.

CREATE EVENT SESSION con destino event_file

Este es un ejemplo de CREATE EVENT SESSION con una cláusula ADD TARGET que agrega un destino event_file.

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() function

El destino event_file almacena los datos que recibe en un formato binario que no es legible por el usuario. La función sys.fn_xe_file_target_read_file te permite representar el contenido de un archivo xel como un conjunto de filas relacional.

Para SQL Server 2016 y versiones posteriores, usa una instrucción SELECT similar al ejemplo siguiente.

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;

Para SQL Server 2014, usa una instrucción SELECT similar al ejemplo siguiente. Después de SQL Server 2014, ya no se usan los archivos 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;

En ambos ejemplos, el carácter comodín * se usa para leer todos los archivos xel que comienzan con el prefijo especificado.

En Azure SQL Database, puedes llamar a la función sys.fn_xe_file_target_read_file() después de crear una credencial con ámbito de base de datos que contenga un token de SAS con los permisos Read y List en el contenedor con los blobs xel:

/*
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;

En Azure SQL Database, puedes llamar a la función sys.fn_xe_file_target_read_file() después de crear un servidor que contenga credenciales con un token de SAS con los permisos Read y List en el contenedor con los blobs xel:

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;

Sugerencia

Si especificas un prefijo de nombre de blob en lugar del nombre completo del blob en el primer argumento de sys.fn_xe_file_target_read_file(), la función devolverá datos de todos los blobs del contenedor que coincidan con el prefijo. Esto te permite recuperar datos de todos los archivos de sustitución de una sesión de eventos determinada sin usar el carácter comodín *, que no es compatible con Azure Storage.

En los ejemplos anteriores de Azure SQL se omite la extensión xel para leer todos los archivos de sustitución incremental de una sesión denominada event-session-1.

Datos almacenados en el destino event_file

Este es un ejemplo de datos devueltos desde sys.fn_xe_file_target_read_file en SQL Server 2016 (13.x) y versiones posteriores.

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

Destino histogram

El destino histogram puede:

  • Contar repeticiones de varios elementos por separado
  • Contar repeticiones de diversos tipos de elementos:
    • Campos del evento
    • Acciones

El destino histogram procesa los datos que recibe de forma sincrónica.

El parámetro source_type es la clave para controlar el destino histogram:

  • source_type=0: recopila datos para un campo de evento.
  • source_type=1: recopila datos de una acción. Este es el valor predeterminado.

El valor predeterminado del parámetro slots es 256. Si asigna otro valor, este se redondea a la siguiente potencia de 2. Por ejemplo, slots=59 se redondearía a 64. El número máximo de ranuras de histograma para un destino histogram es 16 384.

Al usar histogram como destino, puedes ver resultados inesperados. Es posible que algunos eventos no aparezcan en las ranuras esperadas, mientras que otras ranuras podrían mostrar un recuento superior al esperado de eventos.

Esto puede ocurrir si se produce una colisión hash al asignar eventos a ranuras. Aunque esto es poco frecuente, si se produce una colisión hash, se cuenta un evento en una ranura en la que no debería contarse. Por este motivo, se debe tener cuidado al suponer que no se produjo un evento solo porque el recuento en una ranura determinada se muestre como cero.

Por ejemplo, tenga en cuenta el siguiente caso:

  • Configura una sesión de Eventos extendidos, con histogram como destino y agrupación por object_id, para recopilar la ejecución de procedimientos almacenados.
  • Ejecute el procedimiento almacenado A; a continuación, ejecute el procedimiento almacenado B.

Si la función hash devuelve el mismo valor de object_id para ambos procedimientos almacenados, el histograma mostrará el procedimiento almacenado A que se ejecuta dos veces y el procedimiento almacenado B no aparecerá.

Para mitigar este problema cuando el número de valores distintos es relativamente pequeño, establece el número de ranuras de histograma superiores al cuadrado de los valores distintos esperados. Por ejemplo, si el destino histogram tiene establecido source en el campo de eventos table_name y hay 20 tablas en la base de datos, 20*20 = 400. La siguiente potencia de 2 mayor que 400 es 512, que es el número recomendado de ranuras en este ejemplo.

Destino del histograma con una acción

En su cláusula ADD TARGET ... (SET ...), la siguiente instrucción CREATE EVENT SESSION especifica la asignación de parámetros de destino source_type=1. Esto significa que el destino histogram realiza un seguimiento de una acción.

En el presente ejemplo, la cláusula ADD EVENT ... (ACTION ...) ofrece solamente una acción para elegir, concretamente sqlos.system_thread_id. En la cláusula ADD TARGET ... (SET ...), vemos la asignación source=N'sqlos.system_thread_id'.

Nota:

No es posible agregar más de un destino del mismo tipo por sesión de eventos. Esto incluye el destino histogram. Tampoco es posible tener más de un origen (campo de acción o evento) por destino de histogram. Por lo tanto, se requiere una nueva sesión de eventos para realizar un seguimiento de cualquier acción o campos de acción adicionales en un destino histogram individual.

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
        );

Se capturaron los siguientes datos. Los valores de la columna value son valores system_thread_id. Por ejemplo, se realizaron un total de 236 bloqueos en el subproceso 6540.

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

SELECT para descubrir las acciones disponibles

La instrucción C.3 SELECT puede encontrar las acciones que el sistema tiene a su disposición para que las especifique en la instrucción CREATE EVENT SESSION. En la cláusula WHERE, primero editarías el filtro o.name LIKE para hacerlo coincidir con las acciones que te interesan.

A continuación se muestra un conjunto de filas de ejemplo devuelto por la instrucción C.3 SELECT. La acción system_thread_id está presente en la segunda fila.

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

Destino del histograma con un campo de evento

En el ejemplo siguiente se establece source_type=0. El valor asignado a source es un campo de evento.

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
    );

El destino histogram capturó los siguientes datos. Los datos muestran que la base de datos con el ID 5 experimentó siete eventos checkpoint_begin.

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

SELECT para descubrir los campos disponibles en el evento elegido

La instrucción C.4 SELECT muestra los campos de evento de entre los que puede elegir. Primero editaría el filtro o.name LIKE para hacerlo coincidir con el nombre de evento elegido.

La instrucción SELECT devolvió el siguiente conjunto de filas (C.4). El conjunto de filas muestra que database_id es el único campo del evento checkpoint_begin que puede proporcionar valores para el destino histogram.

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

Destino pair_matching

El destino pair_matching permite detectar eventos de inicio que se producen sin un evento de finalización correspondiente. Por ejemplo, podría suponer un problema el hecho de que se produjera un evento lock_acquired, pero no le siguiera ningún evento lock_released coincidente de forma puntual.

El sistema no hace coincidir automáticamente los eventos de inicio y finalización. En su lugar, explica la coincidencia al sistema en la instrucción CREATE EVENT SESSION. Al coincidir un evento de inicio y finalización, el par se descarta para centrarse en los eventos de inicio no coincidentes.

Buscar campos coincidentes para el par de eventos de inicio y finalización

Mediante el uso de la instrucción SELECT C.4, vemos en el siguiente conjunto de filas que hay unos 16 campos para el evento lock_acquired. El conjunto de filas aquí mostrado se ha dividido manualmente para hacer visibles los campos en los que coincidía nuestro ejemplo. Para algunos campos como duration, intentar buscar coincidencias no tiene sentido.

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

Un ejemplo del destino de pair_matching

La siguiente instrucción CREATE EVENT SESSION especifica dos eventos y dos destinos. El destino pair_matching especifica dos conjuntos de campos para que coincidan con los eventos en pares. La secuencia de campos delimitados por comas asignados a begin_matching_columns y end_matching_columns debe ser la misma. No se permiten pestañas ni nuevas líneas entre los campos mencionados en el valor delimitado por comas, aunque sí se permiten los espacios.

Para restringir los resultados, primero realizamos una selección a partir de sys.objects para buscar el valor object_id de nuestra tabla de prueba. Hemos agregado un filtro para ese identificador de objeto en la cláusula ADD EVENT ... (WHERE ...).

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
    );

Para probar la sesión de eventos, impedimos expresamente la liberación de dos bloqueos adquiridos. Lo hicimos con los siguientes pasos de T-SQL:

  1. BEGIN TRANSACTION.
  2. UPDATE MyTable....
  3. No emitas intencionadamente COMMIT TRANSACTION, hasta después de examinar los destinos.
  4. Más adelante después de las pruebas, emitimos COMMIT TRANSACTION.

El destino event_counter sencillo proporcionó las siguientes filas de salida. Como 52-50=2, el resultado implica que vemos dos eventos lock_acquired desemparejados al examinarse este desde el destino de coincidencia de pares.

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

El destino pair_matching proporcionó el siguiente resultado. Como sugiere la salida event_counter, en realidad vemos las dos filas lock_acquired. El hecho de que veamos estas filas significa que estos eventos lock_acquired están desemparejados.

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

Las filas de los eventos no emparejados lock_acquired podrían incluir el texto T-SQL proporcionado por la acción sqlserver.sql_text. Esto captura la consulta que adquirió los bloqueos.

destino ring_buffer

El destino ring_buffer es útil solo para una recopilación de eventos rápida y sencilla en memoria. Cuando detiene la sesión de eventos, se descarta el resultado almacenado.

En esta sección, también mostramos cómo puedes usar XQuery para convertir la representación XML de contenidos de búfer en anillo en un conjunto de filas relacional más legible.

Sugerencia

Al agregar un destino ring_buffer, establezca su parámetro MAX_MEMORY en 1024 KB o menos. El uso de valores más grandes podría aumentar innecesariamente el consumo de memoria.

De forma predeterminada, MAX_MEMORY para un destino ring_buffer no tiene limitaciones en SQL Server, pero tiene un límite de 32 MB en Azure SQL Database y Azure SQL Managed Instance.

Consumes datos de un destino ring_buffer al convertirlo en XML, como se muestra en el ejemplo siguiente. Durante esta conversión, se omiten los datos que no caben en un documento XML de 4 MB. Por lo tanto, incluso si capturas más eventos en el búfer en anillo mediante valores MAX_MEMORY más grandes (o dejando este parámetro en su valor predeterminado), es posible que no puedas consumirlos todos debido al límite de 4 MB en el tamaño del documento XML, teniendo en cuenta la sobrecarga del marcado XML y las cadenas Unicode.

Sabes que el contenido del búfer en anillo se omite durante la conversión a XML si el atributo truncated del documento XML está establecido en 1, por ejemplo:

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

CREATE EVENT SESSION con un destino ring_buffer

Este es un ejemplo de creación de una sesión de eventos con un destino ring_buffer. En este ejemplo, el parámetro MAX_MEMORY aparece dos veces: una vez para establecer la memoria de destino ring_buffer en 1024 KB y una vez para establecer la memoria del búfer de sesión de eventos en 2 MB.

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
    );

Resultado XML recibido para lock_acquired por el destino ring_buffer

Cuando se recupera mediante una instrucción SELECT, el contenido de un búfer en anillo se presenta como un documento XML. Se muestra un ejemplo a continuación. Sin embargo, por brevedad, se han quitado todos los elementos, salvo dos elementos <event>. Además, dentro de cada <event>, también se han eliminado un puñado de elementos <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>

Para ver el código XML anterior, puedes emitir la instrucción SELECT siguiente mientras la sesión de eventos está activa. Los datos XML se recuperan de la vista del sistema 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;

XQuery para ver el código XML como un conjunto de filas

Para ver el código XML anterior como un conjunto de filas relacional, continúe desde la instrucción SELECT anterior mediante la emisión de la siguiente extensión T-SQL. Las líneas comentadas explican cada uso de 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);

Notas de XQuery de la instrucción SELECT anterior

(A)

  • timestamp= el valor del atributo, en el elemento <event>.
  • La construcción '(...)[1]' garantiza solo la devolución de un valor por iteración, al tratarse de una limitación requerida del método XQuery .value() de la variable y las columnas de tipo de datos XML.

(B)

  • Valor interno del elemento <text>, dentro de un elemento <data>; cuyo atributo name= equivale a mode.

(C)

  • Valor interno de los elementos <value>, dentro de un elemento <data>; cuyo atributo name= equivale a transaction_id.

(D)

  • <event> contiene <action>.
  • Teniendo <action> un atributo name= equivalente a database_name y un atributo package= equivalente a sqlserver (no a package0), obtén el valor interno del elemento <value>.

(E)

  • CROSS APPLY hace que el procesamiento se repita para cada elemento <event> individual cuyo atributo name equivale a lock_acquired.
  • Esto se aplica al código XML devuelto por la cláusula FROM anterior.

Resultados de la instrucción SELECT de XQuery

A continuación se muestra el conjunto de filas generado por la extensión T-SQL anterior que incluye XQuery.

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 target

El destino event_stream puede usarse en programas de .NET escritos en lenguajes como C#. C# y otros desarrolladores de .NET pueden tener acceso a un flujo de eventos a través de una clase de .NET Framework, como, por ejemplo, en el espacio de nombres Microsoft.SqlServer.XEvents.Linq. Este destino no se puede usar en T-SQL.

En caso de aparecer el error 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.) al leer desde el destino event_stream, significa que el flujo de eventos se llenó de datos más rápido de lo que el cliente tardaría en consumirlos. Esto hace que el motor de base de datos se desconecte del flujo de eventos para evitar perjudicar el rendimiento del motor de base de datos.

Espacios de nombres de XEvent