SqlDependency 有哪些限制?

发布于 2024-12-07 05:18:42 字数 166 浏览 1 评论 0原文

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

SqlServer 上还有哪些其他限制/影响?

I am using a table as a message queue and "signing up" for updates by using a SqlDependency. Everywhere I read, people are saying "look out for the limitations of it" but not specifically saying what they are. From what I've gathered, you will have problems when the table has very high update frequency; fortunately, I'm only looking at 10 - 20 values per minute maximum.

What are the other limitations/impact on the SqlServer?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

蓝天 2024-12-14 05:18:42

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

  • 必须明确声明 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。
  • 该语句不得引用同义词。
  • 语句不得包含基于 double/real 数据类型的比较或表达式。
  • 该语句不得使用 TOP 表达式。

其他参考:

The most complete list I can find (from here) is as follows:

  • The projected columns in the SELECT statement must be explicitly stated, and table names must be qualified with two-part names. Notice that this means that all tables referenced in the statement must be in the same database.
  • The statement may not use the asterisk (*) or table_name.* syntax to specify columns.
  • The statement may not use unnamed columns or duplicate column names.
  • The statement must reference a base table.
  • The statement must not reference tables with computed columns.
  • The projected columns in the SELECT statement may not contain aggregate expressions unless the statement uses a GROUP BY expression. When a GROUP BY expression is provided, the select list may contain the aggregate functions COUNT_BIG() or SUM(). However, SUM() may not be specified for a nullable column. The statement may not specify HAVING, CUBE, or ROLLUP.
  • A projected column in the SELECT statement that is used as a simple expression must not appear more than once.
  • The statement must not include PIVOT or UNPIVOT operators.
  • The statement must not include the UNION, INTERSECT, or EXCEPT operators.
  • The statement must not reference a view.
  • The statement must not contain any of the following: DISTINCT, COMPUTE or COMPUTE BY, or INTO.
  • The statement must not reference server global variables (@@variable_name).
  • The statement must not reference derived tables, temporary tables, or table variables.
  • The statement must not reference tables or views from other databases or servers.
  • The statement must not contain subqueries, outer joins, or self-joins.
  • The statement must not reference the large object types: text, ntext, and image.
  • The statement must not use the CONTAINS or FREETEXT full-text predicates.
  • The statement must not use rowset functions, including OPENROWSET and OPENQUERY.
  • The statement must not use any of the following aggregate functions: AVG, COUNT(*), MAX, MIN, STDEV, STDEVP, VAR, or VARP.
  • The statement must not use any nondeterministic functions, including ranking and windowing functions.
  • The statement must not contain user-defined aggregates.
  • The statement must not reference system tables or views, including catalog views and dynamic management views.
  • The statement must not include FOR BROWSE information.
  • The statement must not reference a queue.
  • The statement must not contain conditional statements that cannot change and cannot return results (for example, WHERE 1=0).
  • The statement can not specify READPAST locking hint.
  • The statement must not reference any Service Broker QUEUE.
  • The statement must not reference synonyms.
  • The statement must not have comparison or expression based on double/real data types.
  • The statement must not use the TOP expression.

Additional reference:

ゃ人海孤独症 2024-12-14 05:18:42

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

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

    如果

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

In addition to this, for anyone else thinking about using SqlDependency to receive notifications about changes, I've been using this approach in production, and I'm finding problems with it. I'm looking into it to see if the problems are related to my code, but the main issues are:

  • If you fire multiple changes in quick succession, you don't always get the equivalent number of events coming through to the code. In my code, if 2 new records are inserted one after the other, I only get the one notification (for the last one).

  • There is no way to know the record that was added. So if you add a new record, and the code fires to receive the notification, there is no way in the code to know the id of that new record, so you need to query the database for it.

纵山崖 2024-12-14 05:18:42

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

例如,此 select 在 SQL Management Studio 中工作正常:

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

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

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

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

Update

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

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

Spent a day chasing down an issue with SQL Service Broker not working, the root cause was referencing the database in the stored procedure.

For example, this select works fine in SQL Management Studio:

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

However, this is rejected by SQL Service Broker because we are referencing the database in the select statement, and the callback from SqlDependency comes back with Invalid in SqlNotificationEventArgs e, see http://msdn.microsoft.com/en-us/library/ms189308.aspx.

Altering the SQL passed into SqlDependency to the following statement eliminated the error:

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

Update

The example above is just one of many, many limitations to the SQL statement that SQL Service Broker depends on. For a complete list of limitations, see What are the limitations of SqlDependency.

The reason? The SQL statement that SQL Service Broker uses is converted, behind the scenes, into instructions to monitor the SQL Transaction Log for changes to the database. This monitoring is performed in the core of SQL Server, which makes it extremely fast when it comes to detecting changes to table(s). However, this speed comes at a cost: you can't use just any SQL statement, you must use one that can be converted into instructions to monitor the SQL Transaction Log.

千紇 2024-12-14 05:18:42

请注意,您不能在存储过程中使用 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

Note that you cannot use a nolock hint in the stored procedure or the dependency will remain constantly invalid and therefore any cache you make on it will permanently re-query the database.

with (NOLOCK) 

This does not appear to be mentioned in the documentation (as far as I can tell).

The following SET options are required prior to the procedure script

SET ANSI_NULLS ON
SET ANSI_PADDING ON  
SET ANSI_WARNINGS ON

Others have argued that these SET options are also required, but I don't think they are. It's a good idea to set them like this anyway though.

SET CONCAT_NULL_YIELDS_NULL ON 
SET QUOTED_IDENTIFIER ON 
SET NUMERIC_ROUNDABORT OFF 
SET ARITHABORT ON
ゃ人海孤独症 2024-12-14 05:18:42

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

Another big issue I have with this technology: the need for the subscriber connection to have Create Procedure permissions. The web service layer of my application at work at the moment runs as a restricted user. To get notifications setup using SQLDependency I'd have to open up that user to create procs. Sounds like a pretty good step along the path of getting owned.

我ぃ本無心為│何有愛 2024-12-14 05:18:42

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

To overcome these limitations, you can try use the SqlTableDependency.
Have a look at www.sqltabledependency.it

心如荒岛 2024-12-14 05:18:42

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

https://learn.microsoft.com/en-我们/azure/sql-database/sql-database-features

服务代理

由单一数据库和弹性池支持:

没有

受托管实例支持:

是的,但仅限于实例内。
请参阅 服务代理差异

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

It uses Service Broker. Therefore it won't work on non managed SQL Azure instances. So be cautious if you're using SQL Azure or ever might.

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

Service Broker

Supported by single databases and elastic pools:

No

Supported by managed instances:

Yes, but only within the instance.
See Service Broker differences

So probably not a good fit unless all your environments can use it!

多像笑话 2024-12-14 05:18:42

SqlDependency 不适用于内存优化表。我在文档中没有找到它,但在我的应用程序中却没有。

SqlDependency does not work with memory-optimized tables. I did not find it in the documentation but in my app it does not.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文