Поделиться через


Использование WQL с поставщиком WMI для событий сервера

Область применения: SQL Server

Приложения управления получают доступ к событиям SQL Server с помощью поставщика WMI для событий сервера путем выдачи инструкций WMI Language (WQL). WQL является упрощенным подмножеством языка SQL с некоторыми расширениями, специфичными для WMI. При использовании WQL приложение получает тип события для определенного экземпляра SQL Server, базы данных или объекта базы данных (единственный объект, поддерживаемый в настоящее время— очередь). Поставщик WMI для событий сервера преобразует запрос в уведомление о событии, созданное в целевой базе данных для уведомлений о событиях с областью действия базы данных или объектов, или в master базе данных для уведомлений о событиях на уровне сервера.

Например, рассмотрим следующий WQL-запрос.

SELECT * FROM DDL_DATABASE_LEVEL_EVENTS WHERE DatabaseName = 'AdventureWorks2022'

На основе этого запроса поставщик WMI совершает попытку создать эквивалент этого уведомления о событии на целевом сервере.

USE AdventureWorks2022;
GO

CREATE EVENT NOTIFICATION SQLWEP_76CF38C1_18BB_42DD_A7DC_C8820155B0E9
    ON DATABASE
    WITH FAN_IN
    FOR DDL_DATABASE_LEVEL_EVENTS
    TO SERVICE
        'SQL/Notifications/ProcessWMIEventProviderNotification/v1.0',
        'A7E5521A-1CA6-4741-865D-826F804E5135';
GO

Аргумент в предложении FROM WQL-запроса (DDL_DATABASE_LEVEL_EVENTS) может представлять любое допустимое событие, о котором может быть создано уведомление. Аргументы в предложениях SELECT и WHERE могут указывать любые свойства событий, связанные с событием или его родительским событием. Список допустимых событий и свойств событий см. в разделе "Уведомления о событиях" (ядро СУБД).

Следующий синтаксис языка WQL явно поддерживается поставщиком WMI для событий сервера. Можно указать дополнительный синтаксис WQL, но он не предназначен для этого поставщика и анализируется службой узлов WMI. Дополнительные сведения о языке запросов WMI см. в документации по WQL на веб-узле MSDN.

Синтаксис

SELECT { event_property [ , ...n ] | * }
FROM event_type
WHERE where_condition
[ ; ]

Аргументы

event_property [ , ... n ] | *

Свойство события. Например, PostTime, SPID и LoginName. Найдите каждое событие, указанное в поставщике WMI для классов и свойств событий сервера, чтобы определить, какие свойства он содержит. Например, событие DDL_DATABASE_LEVEL_EVENTS имеет свойства DatabaseName и UserName. Также оно наследует свойства SQLInstance, LoginName, PostTime, SPID и ComputerName от родительских событий.

  • , ... n

    Указывает, что event_property можно запрашивать несколько раз, разделенных запятыми.

  • *

    Указывает, что запрашиваются все свойства, связанные с событием.

event_type

Любое событие, для которого можно создать уведомление о событии. Список доступных событий см. в разделе "Поставщик WMI" для классов и свойств событий сервера. Имена типов событий соответствуют тем же event_type event_group | , которые можно указать при создании уведомления о событии вручную с помощью.CREATE EVENT NOTIFICATION Примеры типа события: CREATE_TABLE, LOCK_DEADLOCKи DDL_USER_EVENTSTRC_DATABASE.

Примечание.

Определенные системные хранимые процедуры, выполняющие DDL-подобные операции, могут также вызывать формирование уведомления о событиях. Протестируйте свои уведомления о событиях, чтобы определить их реакцию на системные хранимые процедуры. Например, CREATE TYPE инструкция и sp_addtype хранимая процедура будут запускать уведомление о событии, созданное в событии CREATE_TYPE . Однако хранимая sp_rename процедура не запускает уведомления о событиях. Дополнительные сведения см. в разделе "События DDL".

where_condition

Предикат WHERE запроса предложения, состоящий из event_property имен и логических и операторов сравнения. Where_condition определяет область, в которой соответствующее уведомление о событии зарегистрировано в целевой базе данных. Он также может выступать в качестве фильтра для целевой схемы или объекта, из которого запрашивать event_type. Дополнительные сведения см. в разделе "Примечания".

Только операнд = может использоваться вместе с DatabaseName, SchemaName и ObjectName. Другие выражения нельзя использовать с этими свойствами события.

Замечания

Where_condition поставщика WMI для событий сервера определяет следующее:

  • Область, с помощью которой поставщик пытается получить указанные event_type: уровень сервера, уровень базы данных или уровень объекта (единственный объект, поддерживаемый в настоящее время, — очередь). В конечном счете эта область определяет тип уведомления о событии, создаваемого в базе данных-получателе. Этот процесс называется регистрацией уведомления о событии.

  • База данных, схема и объект (если применимо), в которых выполняется регистрация.

Поставщик WMI для событий сервера использует алгоритм снизу вверх, подходящий для создания максимально узкой области для базовой EVENT NOTIFICATIONсреды. Алгоритм пытается свести к минимуму внутренние действия на сервере и сетевом трафике между экземпляром SQL Server и процессом узла WMI. Поставщик проверяет event_type , указанные в FROM предложении, и условия в WHERE предложении, и пытается зарегистрировать базовый EVENT NOTIFICATION объект с максимальной возможной областью. Если поставщик не может зарегистрировать в самой узкой области, он пытается зарегистрировать в последовательно более высоких областях до тех пор, пока регистрация, наконец, не будет успешно выполнена. Если достигнут самый высокий уровень (уровень сервера), а регистрация завершается сбоем, возвращается сообщение об ошибке.

Например, если DatabaseName='AdventureWorks2022' указано в WHERE предложении, поставщик пытается зарегистрировать уведомление о событии AdventureWorks2022 в базе данных. Если база данных AdventureWorks2022 существует, а у вызывающего клиента достаточно разрешений для создания уведомления в AdventureWorks2022, регистрация выполняется успешно. В противном случае выполняется попытка зарегистрировать уведомление о событии на уровне сервера. Регистрация выполняется успешно, если клиент WMI имеет необходимые разрешения. Однако в этом сценарии события не возвращаются клиенту, пока AdventureWorks2022 база данных не будет создана.

Where_condition также может выступать в качестве фильтра, чтобы дополнительно ограничить запрос определенной базой данных, схемой или объектом. Например, рассмотрим следующий WQL-запрос.

SELECT * FROM ALTER_TABLE
WHERE DatabaseName = 'AdventureWorks2022' AND SchemaName = 'Sales'
    AND ObjectType='Table' AND ObjectName = 'SalesOrderDetail'

В зависимости от результата процесса регистрации этот запрос WQL может быть зарегистрирован на уровне базы данных или сервера. Однако даже если он зарегистрирован на уровне сервера, поставщик в конечном итоге фильтрует любые ALTER_TABLE события, которые не применяются к Sales.SalesOrderDetail таблице. Иными словами, поставщик возвращает только свойства событий ALTER_TABLE, возникших в конкретной таблице.

Если указано составное выражение DatabaseName='AW1' OR DatabaseName='AW2' , попытка зарегистрировать одно уведомление о событии в области сервера вместо двух отдельных уведомлений о событиях. Регистрация выполняется успешно, если вызывающий клиент имеет необходимые разрешения.

Если SchemaName='X' AND ObjectType='Y' AND ObjectName='Z' все указано в WHERE предложении, попытка зарегистрировать уведомление о событии непосредственно в объекте Z в схеме X. Регистрация выполняется успешно, если клиент имеет необходимые разрешения. В настоящее время события уровня объектов поддерживаются только в очередях и только для QUEUE_ACTIVATION event_type.

Не все события можно запрашивать в любой конкретной области. Например, запрос WQL на событие трассировки, например Lock_Deadlock, или группу событий трассировки, например TRC_LOCKS, можно зарегистрировать только на уровне сервера. Аналогичным образом CREATE_ENDPOINT событие и DDL_ENDPOINT_EVENTS группа событий также могут быть зарегистрированы только на уровне сервера. Дополнительные сведения о соответствующей области регистрации событий см. в разделе "Проектирование уведомлений о событиях". Попытка зарегистрировать WQL-запрос, event_type которого можно зарегистрировать только на уровне сервера, всегда выполняется на уровне сервера. Регистрация выполняется успешно, если клиент WMI имеет необходимые разрешения. Иначе клиенту возвращается ошибка. Однако в некоторых случаях предложение по-прежнему можно использовать WHERE в качестве фильтра для событий на уровне сервера на основе свойств, соответствующих событию. Например, многие события трассировки имеют DatabaseName свойство, которое можно использовать в предложении в WHERE качестве фильтра.

Уведомления о событиях на уровне сервера создаются в master базе данных и могут запрашиваться для метаданных с помощью представления каталога sys.server_event_notifications .

Уведомления о событиях с областью действия базы данных или объекта создаются в указанной базе данных и могут запрашиваться для метаданных с помощью представления каталога sys.event_notifications . Представление каталога должно иметь префикс с именем соответствующей базы данных.

Примеры

Примеры кода Transact-SQL в этой статье используют AdventureWorks2022 базу данных или AdventureWorksDW2022 пример базы данных, которую можно скачать с домашней страницы примеров и проектов сообщества Microsoft SQL Server.

А. Запрос событий в области сервера

Следующий запрос WQL извлекает все свойства события для любого SERVER_MEMORY_CHANGE события трассировки, которое происходит в экземпляре SQL Server.

SELECT * FROM SERVER_MEMORY_CHANGE

B. Запрос событий в области базы данных

Следующий WQL-запрос получает конкретные свойства событий для любых событий, возникающих в базе данных AdventureWorks2022 и существующих в группе событий DDL_DATABASE_LEVEL_EVENTS.

SELECT SPID, SQLInstance, DatabaseName FROM DDL_DATABASE_LEVEL_EVENTS
WHERE DatabaseName = 'AdventureWorks2022'

В. Запрос событий в области базы данных, фильтрация по схеме и объекту

Следующий запрос получает все свойства событий для любого события ALTER_TABLE, возникшего в таблице Sales.SalesOrderDetail.

SELECT * FROM ALTER_TABLE
WHERE DatabaseName = 'AdventureWorks2022' AND SchemaName = 'Sales'
    AND ObjectType='Table' AND ObjectName = 'SalesOrderDetail'