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


Блокировки группы сообщений

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

Все диалоги принадлежат группе сообщений. По умолчанию каждый диалог принадлежит собственной группе сообщений и поэтому диалоги обладают различными идентификаторами группы сообщений. Инструкция MOVE CONVERSATION изменяет группу сообщений для диалога. Инструкция BEGIN DIALOG CONVERSATION содержит параметры, позволяющие сопоставить новый диалог с существующей группой сообщений. Дополнительные сведения о группах сообщений см. в разделе Группы сообщений.

Блокировка группы сообщений фактически является монопольной блокировкой набора сообщений, которые имеют одинаковый идентификатор группы сообщений. Блокировки группы сообщений предназначены для упрощения работы, повышения эффективности и точности. Для получения или снятия блокировки группы сообщений нет явной команды или подсказки. Вместо этого каждая команда компонента Service Broker, которая распространяется на диалог или группу сообщений, автоматически получает необходимую блокировку группы сообщений. Например, инструкция BEGIN DIALOG блокирует группу сообщений, которой принадлежит новый диалог, а инструкция RECEIVE блокирует группу сообщений, которой принадлежат получаемые сообщения.

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

Блокировка выполняется для группы сообщений, а не для идентификатора диалога. Поэтому блокировка применяется только к одной стороне диалога, даже если инициатор и целевой объект находятся в одной базе данных. Блокировка, полученная целевой службой, не блокирует вызывающую службу, и наоборот. Кроме того, компонент Database Engine не соблюдает блокировку во время добавления входящих сообщений в очередь. Компонент Database Engine добавляет сообщения в очередь даже в случае, когда приложение удерживает блокировку для группы сообщений, которой принадлежат сообщения.

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

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

Такая стратегия блокировки позволяет компоненту Service Broker гарантировать обработку сообщений в соответствии с порядком. Поскольку сообщения для заданной группы сообщений могут обрабатываться только одним агентом чтения очереди, отсутствует риск возникновения ситуации, в которой два агента чтения очереди одновременно получат сообщения из одной группы сообщений. Для заданного диалога инструкция RECEIVE возвращает сообщения в порядке, в котором они были отправлены, поэтому несколько агентов чтения очереди могут обрабатывать сообщения из очереди без необходимости явной координации порядка.

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

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

Следующие инструкции получают блокировки группы сообщений:

См. также

Справочник

Основные понятия