Работа с уведомлениями запросов

Уведомления о запросах появились в SQL Server 2005 и в собственном клиенте SQL Server. С помощью уведомлений о запросах, построенных на основе инфраструктуры компонента Service Broker, представленной в SQL Server 2005, приложения могут получать извещения об изменениях данных. Эта функция особенно полезна для приложений, которые предоставляют кэш данных из базы данных (например, для веб-приложений), и которым требуются уведомления об изменении исходных данных.

С помощью уведомлений о запросах можно запрашивать уведомления в течение указанного времени ожидания при изменении базовых данных запроса. В запросе на уведомление указываются параметры уведомления, среди которых имя службы, текст сообщения и значение времени ожидания для сервера. Доставка уведомлений осуществляется через очередь компонента SQL Service Broker, которую приложения могут опрашивать на предмет имеющихся уведомлений.

Строка параметров уведомлений запросов имеет следующий синтаксис.

service=<service-name>[;(local database=<database> | broker instance=<broker instance>)]

Например,

service=mySSBService;local database=mydb

Подписки на уведомления переживают процесс, который их инициирует, поскольку приложение может создать подписку на уведомление, а затем завершиться. Подписка остается действительной, а уведомление будет отправлено в случае изменения данных в течение времени ожидания, указанного при создании подписки. Уведомление определяется выполненным запросом, параметрами уведомления, а также текстом сообщения. Его можно отменить, установив нуль в качестве значения времени ожидания.

Уведомления отправляются только один раз. Чтобы получать постоянные уведомления об изменении данных, необходимо создавать новую подписку после обработки каждого уведомления путем повторного выполнения запроса.

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

ПримечаниеПримечание

В запросах необходимо указывать имена таблиц, для которых требуется отправлять уведомления, например dbo.myTable. Имена таблиц должны состоять из двух частей. Подписка будет недействительной в случае использования имен из трех или четырех частей.

Инфраструктура уведомлений построена поверх функции запросов, которая появилась в SQL Server 2005. В общем уведомления, формируемые на сервере, отправляются через эти запросы для последующей обработки. Дополнительные сведения о поддержке уведомлениях о запросах в SQL Server см в разделе Использование уведомлений запросов.

Чтобы использовать уведомления о запросах, очередь и служба должны существовать на сервере. Их можно создать при помощи Transact-SQL следующим образом:

CREATE QUEUE myQueueCREATE SERVICE myService ON QUEUE myQueue ([https://schemas.microsoft.com/SQL/Notifications/PostQueryNotification])
ПримечаниеПримечание

Служба должна использовать предопределенный контракт https://schemas.microsoft.com/SQL/Notifications/PostQueryNotification, показанный выше.

Поставщик OLE DB для собственного клиента SQL Server

Поставщик OLE DB собственного клиента SQL Server поддерживает уведомление потребителей об изменении набора строк. Потребитель получает уведомление на каждой стадии изменения набора строк, а также при каждой попытке внести изменение.

ПримечаниеПримечание

Передача серверу запроса на уведомления с методом ICommand::Execute является единственным допустимым способом подписки на уведомления о запросах с помощью поставщика OLE DB собственного клиента SQL Server.

Набор свойств DBPROPSET_SQLSERVERROWSET

Чтобы поддерживать отправку уведомлений о запросах через OLE DB, собственный клиент SQL Server добавляет в набор свойств DBPROPSET_SQLSERVERROWSET следующие новые свойства.

Имя

Тип

Описание

SSPROP_QP_NOTIFICATION_TIMEOUT

VT_UI4

Время в секундах, в течение которого уведомление запроса должно оставаться активным.

Значение по умолчанию — 432000 секунд (5 дней). Минимальное значение — 1 секунда, а максимальное значение — 2^31-1 секунд.

SSPROP_QP_NOTIFICATION_MSGTEXT

VT_BSTR

Текст сообщения уведомления. Определяется пользователем и не имеет предопределенного формата.

По умолчанию эта строка пуста. В сообщении можно использовать от 1 до 2000 символов.

SSPROP_QP_NOTIFICATION_OPTIONS

VT_BSTR

Параметры уведомлений запросов. Эти параметры указываются в строке с использованием синтаксиса имя=значение. За создание службы и считывание уведомлений из очереди отвечает пользователь.

Значением по умолчанию является пустая строка.

Подписка на уведомления всегда фиксируется, независимо от того, выполнялась ли инструкция в рамках пользовательской транзакции или в режиме AUTO COMMIT, а также была ли транзакция, в рамках которой выполнялась инструкция, зафиксирована либо был выполнен ее откат. Уведомление сервера срабатывает при возникновении любого из следующих недопустимых условий: изменение базовых данных или схемы, либо по истечении времени ожидания, в зависимости от того, что произойдет первым. Регистрации уведомлений удаляются сразу же после их срабатывания. Поэтому, если приложению требуется получение уведомлений в дальнейшем, оно должно подписаться на них снова сразу после получения уведомления.

Другое соединение или поток может проверять целевую очередь на наличие уведомлений. Например,

WAITFOR (RECEIVE * FROM MyQueue);   // Where MyQueue is the queue name. 

Следует отметить, что инструкция SELECT * не удаляет какие-либо записи из очереди, а вот инструкция RECEIVE * FROM удаляет. Если очередь пуста, поток сервера будет остановлен. При наличии в очереди записей в момент вызова они возвращаются мгновенно; в противном случае, вызов ожидает появления записи в очереди.

RECEIVE * FROM MyQueue

Если очередь пуста, то эта инструкция немедленно возвращает пустой результирующий набор; в противном случае, она возвращает все уведомления в очереди.

Если значение свойств SSPROP_QP_NOTIFICATION_MSGTEXT и SSPROP_QP_NOTIFICATION_OPTIONS не равно NULL и не является пустым, то при каждом выполнении этой команды на сервер отправляется заголовок TDS уведомлений о запросах, содержащий три свойства, указанные выше. Если значение любого из них равно NULL (или пустое), заголовок не отправляется, а формируется DB_E_ERRORSOCCURRED, (или DB_S_ERRORSOCCURRED, если оба свойства обозначены, как необязательные), а значение состояния устанавливается в DBPROPSTATUS_BADVALUE. Поверка выполняется в случае команды Execute/Prepare. Точно так же DB_S_ERRORSOCCURED формируется при задании свойств уведомлений о запросах для установления соединений с SQL Server версий младше SQL Server 2005. В этом случае значение состояния — DBPROPSTATUS_NOTSUPPORTED.

Запуск подписки не гарантирует успешной доставки последующих сообщений. Кроме того, допустимость указанного имени службы также не проверяется.

ПримечаниеПримечание

При подготовке инструкций подписка никогда не запускается. Запуск подписки происходит только при выполнении инструкций, а использование базовых служб OLE DB не оказывает влияния на уведомления о запросах.

Дополнительные сведения о наборе свойств DBPROPSET_SQLSERVERROWSET см. в разделе Свойства и поведение наборов строк.

Драйвер ODBC для собственного клиента SQL Server

Драйвер ODBC собственного клиента SQL Server поддерживает уведомления о запросах путем добавления трех новых атрибутов функциям SQLGetStmtAttr и SQLSetStmtAttr:

  • SQL_SOPT_SS_QUERYNOTIFICATION_MSGTEXT

  • SQL_SOPT_SS_QUERYNOTIFICATION_OPTIONS

  • SQL_SOPT_SS_QUERYNOTIFICATION_TIMEOUT

Если значение свойств SQL_SOPT_SS_QUERYNOTIFICATION_MSGTEXT и SQL_SOPT_SS_QUERYNOTIFICATION_OPTIONS не равно NULL, то при каждом выполнении этой команды на сервер отправляется заголовок TDS уведомлений о запросах, содержащий три атрибута, указанных выше. Если значение любого из них равно NULL, заголовок не отправляется, и возвращается SQL_SUCCESS_WITH_INFO. Выполняется проверка команд SQLPrepare, SqlExecDirect и SqlExecute, при этом все они завершаются неудачей, если эти атрибуты являются недействительными. Точно так же, когда эти атрибуты уведомлений о запросах отправляются для версий SQL Server младше SQL Server 2005, выполнение завершается неудачей с SQL_SUCCESS_WITH_INFO.

ПримечаниеПримечание

Подготовка инструкций никогда не вызывает запуска подписки, подписка может быть запущена выполнением инструкции.

Особые случаи и ограничения

Следующие типы данных для уведомлений не поддерживаются:

  • text

  • ntext

  • image

Если сделан запрос на уведомление о запросе, который возвращает один из этих типов данных, уведомление срабатывает мгновенно с указанием, что выполнить подписку на уведомление невозможно.

Если запрос на подписку сделан для пакета или хранимой процедуры, для каждой инструкции, выполняемой в пакете или хранимой процедуре, будет сделан отдельный запрос на подписку. Инструкция EXECUTE не регистрирует уведомление, но направляет требование об уведомлении выполняемой команде. Если это пакет, к выполняемым инструкциям будет применен контекст и правила, описанные выше.

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