会话组锁

适用范围:SQL ServerAzure SQL 托管实例

Service Broker 采用会话组锁定功能保证在任何给定的时间只有一个队列读取器可以使用一组相关的消息。 Service Broker 采用会话组锁定功能保证按顺序处理这些消息,且仅处理一次。

所有的会话都属于会话组。 默认情况下,每个会话属于不同的聊天组,因此它具有不同的聊天组标识符。 该 MOVE CONVERSATION 语句更改会话的对话组。 该 BEGIN DIALOG CONVERSATION 语句包含用于将新会话与现有聊天组关联的选项。 有关对话组的详细信息,请参阅 对话组

实际上,会话组锁定是共享同一会话组标识符的消息组上的排他锁。 会话组锁定是以简单、高效和正确为宗旨而设计的。 没有用于获取或释放会话组锁的显式命令或提示。 而影响对话或会话组的每个 Service Broker 命令将会自动获取相应的会话组锁定。 例如, BEGIN DIALOG 语句锁定新对话所属的对话组,而 RECEIVE 语句将锁定收到的消息所属的对话组。

在会话已获取锁定的事务期间,会话对会话组保持锁定。 会话不能跨事务保留会话组锁;事务结束时,释放事务期间获取的所有会话组锁。

锁定将针对会话组而不是会话 ID 进行。 因此,即使发起方和接收方都位于同一数据库中,锁定也仅适用于会话的其中一方。 目标服务获取的锁不会阻止启动服务,反之亦然。 此外,数据库引擎不会在将传入消息添加到队列时强制锁定。 即使应用程序对消息所属的对话组具有会话组锁定,数据库引擎也会向队列添加消息。

实际上,这意味着仅使用从 Service Broker 检索到的标识符的应用程序不需要等待获取 Service Broker 资源的锁。 大多数 Service Broker 应用程序旨在利用 Service Broker 提供的锁定;也就是说,大多数 Service Broker 应用程序仅使用从同一事务中的 Service Broker 语句获取的对话组标识符和会话句柄。

例如,应用程序通常从 Service Broker 获取会话组标识符,通过状态表检索状态,然后再处理该会话组中各个会话的消息。 应用程序在获取会话组标识符后,该应用程序即对会话组进行锁定:应用程序的其他实例无法获取该锁定。 但是,会话组锁定不会阻止应用程序的其他实例接收其他会话组的消息,也不会阻止传入消息到达队列。

通过此锁定策略,Service Broker 可以保证按顺序对消息进行处理。 由于只有一个队列读取器可以处理给定聊天组的消息,因此两个队列读取器不会同时接收同一会话组中的消息。 对于特定会话,该 RECEIVE 语句按发送消息的顺序返回消息,因此多个队列读取器可以处理队列中的消息,而无需显式协调排序。

由于锁定对会话组而不是单个会话进行作,因此在语句中 RECEIVE 未指定特定会话的队列读取器可能会从属于同一会话组的不同会话接收消息。 此外,该 RECEIVE 语句将返回队列中的下一个可用消息,无论该消息是当前解锁的会话组的一部分,还是被锁定在当前事务中。 若要从特定会话接收消息,请在语句中 RECEIVE 指定会话句柄。 若要从特定会话组接收消息,请在 RECEIVE 语句中指定会话组标识符。

由于此锁定策略,您的应用程序应首先获取会话组锁定,然后才能更新应用程序的状态表。 大多数情况下,当您的应用程序接收消息或获取会话组时会自动执行此操作。 但是,处理错误时,应用程序可能需要在更新状态表之前重新获取会话组锁,以指示错误。 有关错误处理的详细信息,请参阅 Service Broker 的错误处理

下列语句将获取会话组锁定: