了解排序规则和 Service Broker

Service Broker 可以使具有不同排序规则配置的实例中的服务和应用程序能够轻松、高效地进行通信。作为发送消息的服务的宿主的数据库与作为接收消息的服务的宿主的数据库不得使用相同的“排序规则”。因此,Service Broker 使用一致的名称排序规则,而不考虑作为服务宿主的数据库的排序规则。为了删除通信过程中的排序规则信息,Service Broker 采用逐字节进行比较的方式来匹配服务名称、约定名称和消息类型名称。通过将名称作为字节序列来匹配,Service Broker 使服务正确地交换消息变得更为简单,而且不因交换排序规则信息而产生额外的开销。

逐字节匹配是不考虑当前排序规则的高效二进制比较方法。因此,许多 Broker 服务都发现遵循命名 Service Broker 对象中的建议可以带来很多方便。无论作为目标服务宿主的数据库与作为起始服务宿主的数据库所使用的排序规则是否存在差异,遵照这些准则并将所有名称都视为区分大小写的应用程序应总能正确运行。

队列排序规则注意事项

队列使用一致的排序规则,而不考虑 SQL Server 实例的默认排序规则或作为该队列宿主的数据库的默认排序规则。在 SELECT 语句包含与数据库中另一个表(如用于维护状态的表)进行联接的 JOIN 语句时,如果队列作为该 SELECT 语句的目标,则您可能需要显式指定用于比较的排序规则。

例如,使用消息保持期的应用程序可能需要在应用程序结束会话之前保留会话的某些消息。下面的 Transact-SQL 代码示例保存指定会话中具有表 AuditedMessageTypes 中所列消息类型名称的所有消息。

IF @messageTypeName =
  'https://schemas.microsoft.com/SQL/ServiceBroker/EndDialog'
BEGIN
  INSERT INTO dbo.AuditRecord
    SELECT q.message_type_name, q.message_body
      FROM dbo.ApplicationQueue AS q
        JOIN dbo.AuditedMessageTypes AS am ON
             am.message_type_name = q.message_type_name
             COLLATE Latin1_General_BIN
           AND
             q.conversation_handle = @conversationHandle
   END CONVERSATION @conversationHandle
END

SELECT 语句显式指定用于匹配消息类型名称的二进制比较。由于队列不使用数据库默认排序规则,因此必须使用 COLLATE 子句才能成功执行 am.message_type_name = q.message_type_name 比较。该语句指定二进制排序规则 Latin1_General_BIN 来匹配 Service Broker 用于匹配服务名称的内部比较的行为。

应用程序排序规则注意事项

Service Broker 将消息正文作为二进制数据传输,并且不修改消息的内容。如果应用程序交换区分排序规则的数据,则这些应用程序必须处理任何排序规则差异。交换文本的应用程序通常使用 Unicode 类型来帮助将排序规则问题减到最少。