49

我使用表作为消息队列并使用 SqlDependency“注册”更新。在我阅读的所有地方,人们都在说“注意它的局限性”,但没有具体说明它们是什么。根据我收集的信息,当表的更新频率非常高时,您会遇到问题;幸运的是,我只看到每分钟最多 10 - 20 个值。

对 SqlServer 的其他限制/影响是什么?

4

7 回答 7

69

我能找到的最完整的列表(从这里)如下:

  • SELECT 语句中的投影列必须明确声明,并且表名必须用两部分名称限定。请注意,这意味着语句中引用的所有表都必须在同一个数据库中。
  • 该语句不能使用星号 (*) 或 table_name.* 语法来指定列。
  • 该语句不得使用未命名的列或重复的列名。
  • 该语句必须引用一个基表。
  • 该语句不得引用具有计算列的表。
  • SELECT 语句中的投影列可能不包含聚合表达式,除非该语句使用 GROUP BY 表达式。当提供 GROUP BY 表达式时,选择列表可能包含聚合函数 COUNT_BIG() 或 SUM()。但是,不能为可为空的列指定 SUM()。该语句可能未指定 HAVING、CUBE 或 ROLLUP。
  • SELECT 语句中用作简单表达式的投影列不得出现多次。
  • 该语句不得包含 PIVOT 或 UNPIVOT 运算符。
  • 该语句不得包含 UNION、INTERSECT 或 EXCEPT 运算符。
  • 该语句不得引用视图。
  • 该语句不得包含以下任何内容:DISTINCT、COMPUTE 或 COMPUTE BY 或 INTO。
  • 该语句不得引用服务器全局变量 (@@variable_name)。
  • 该语句不得引用派生表、临时表或表变量。
  • 该语句不得引用来自其他数据库或服务器的表或视图。
  • 该语句不得包含子查询、外部联接或自联接。
  • 该语句不得引用大对象类型:text、ntext 和 image。
  • 该语句不得使用 CONTAINS 或 FREETEXT 全文谓词。
  • 该语句不得使用行集函数,包括 OPENROWSET 和 OPENQUERY。
  • 该语句不得使用以下任何聚合函数:AVG、COUNT(*)、MAX、MIN、STDEV、STDEVP、VAR 或 VARP。
  • 该语句不得使用任何非确定性函数,包括排名和窗口函数。
  • 该语句不得包含用户定义的聚合。
  • 该语句不得引用系统表或视图,包括目录视图和动态管理视图。
  • 该语句不得包含 FOR BROWSE 信息。
  • 该语句不得引用队列。
  • 该语句不得包含无法更改且无法返回结果的条件语句(例如,WHERE 1=0)。
  • 该语句不能指定 READPAST 锁定提示。
  • 该语句不得引用任何 Service Broker QUEUE。
  • 该语句不得引用同义词。
  • 该语句不得具有基于双精度/实数数据类型的比较或表达式。
  • 该语句不得使用 TOP 表达式。

附加参考:

于 2011-09-28T19:40:18.480 回答
13

除此之外,对于考虑使用 SqlDependency 接收有关更改的通知的其他任何人,我一直在生产中使用这种方法,但我发现它存在问题。我正在调查它,看看问题是否与我的代码有关,但主要问题是:

  • 如果您快速连续触发多个更改,您并不总是会获得相同数量的事件通过代码。在我的代码中,如果一个接一个地插入 2 个新记录,我只会收到一个通知(最后一个)。

  • 无法知道添加的记录。因此,如果您添加一条新记录,并且代码触发以接收通知,则代码中无法知道该新记录的 id,因此您需要查询数据库以获取它。

于 2012-06-12T10:32:30.457 回答
10

花了一天时间追查 SQL Service Broker 无法正常工作的问题,根本原因是在存储过程中引用了数据库。

例如,这select在 SQL Management Studio 中运行良好:

select [MyColumn] from [MyDatabase].[MySchema].[MyTable]

但是,这被 SQL Service Broker 拒绝了,因为我们在 select 语句中引用了数据库,并且SqlDependency来自的回调返回Invalidin SqlNotificationEventArgs e,请参阅http://msdn.microsoft.com/en-us/library/ms189308.aspx

将传递给 SqlDependency 的 SQL 更改为以下语句消除了错误:

select [MyColumn] from [MySchema].[MyTable]

更新

上面的示例只是 SQL Service Broker 所依赖的 SQL 语句的众多限制之一。有关限制的完整列表,请参阅SqlDependency 的限制是什么

原因?SQL Service Broker 使用的 SQL 语句在幕后被转换为指令以监控SQL 事务日志以了解对数据库的更改。此监视在 SQL Server 的核心中执行,这使得它在检测表的更改时非常快。但是,这种速度是有代价的:您不能只使用任何 SQL 语句,您必须使用可以转换为指令的语句来监控SQL 事务日志

于 2014-01-31T09:23:58.163 回答
5

请注意,您不能在存储过程中使用 nolock 提示,否则依赖项将始终保持无效,因此您对其进行的任何缓存都将永久重新查询数据库。

with (NOLOCK) 

文档中似乎没有提到这一点(据我所知)。

在过程脚本之前需要以下 SET 选项

SET ANSI_NULLS ON
SET ANSI_PADDING ON  
SET ANSI_WARNINGS ON

其他人认为这些 SET 选项也是必需的,但我不认为它们是必需的。无论如何,将它们设置为这样是个好主意。

SET CONCAT_NULL_YIELDS_NULL ON 
SET QUOTED_IDENTIFIER ON 
SET NUMERIC_ROUNDABORT OFF 
SET ARITHABORT ON
于 2015-04-29T15:32:09.603 回答
3

我在使用这项技术时遇到的另一个大问题是:订阅者连接需要具有创建过程权限。我目前工作的应用程序的 Web 服务层作为受限用户运行。要使用 SQLDependency 获取通知设置,我必须打开该用户来创建 procs。听起来像是在拥有自己的道路上迈出了相当好的一步。

于 2013-12-02T20:16:21.190 回答
3

要克服这些限制,您可以尝试使用 SqlTableDependency。看看 www.sqltabledependency.it

于 2016-10-24T20:57:33.080 回答
1

它使用服务代理。因此,它不适用于非托管 SQL Azure 实例。因此,如果您正在使用 SQL Azure 或曾经使用过,请务必小心。

https://docs.microsoft.com/en-us/azure/sql-database/sql-database-features

服务经纪人

单库和弹性池支持:

受托管实例支持:

是的,但仅限于实例内。请参阅Service Broker 差异

因此,除非您的所有环境都可以使用它,否则可能不太适合!

于 2019-06-26T22:14:55.343 回答