SqlDependency的可靠性?

44

我的现状是,我有一个应用程序需要在数据库表中有新数据到达时得到通知。数据来自外部来源(我无法控制-这是唯一的集成选项)。当有新数据到达时,我的应用程序需要执行某些操作-基本上是查询新数据,处理它,将结果插入到本地表中等。

如果可能的话,我想避免轮询,因为数据预计是实时处理的。 也就是说,确保永远不会错过任何数据是第一要务。

我的问题:

  1. SqlDependency通常被认为是可靠的吗?
  2. 我需要担心竞态条件吗,例如我正在处理一个更改时另一个更改到达?
  3. 当数据库重新启动时会发生什么?我的应用程序能否恢复并再次开始接收更改,还是我需要一种故障转移计时器定期重新订阅通知?
  4. 我阅读的大多数文章都涉及SQL Server 2005。我使用的是SQL Server 2008 R2。 是否有比SqlDependency更喜欢的新技术?
  5. (编辑)还有,如果应用程序关闭了怎么办?我想我必须在启动时查询缺失的数据?

当您说您的应用程序需要执行数据库操作时,是否可能让数据库只执行这些操作? - Kermit
2个回答

55

1) 是的,我认为它是可靠的,因为它能够正确地执行它所设计的用途(缓存失效)。

2) 不是。这就是为什么你只能通过发出查询来订阅,这确保了在获取数据和新更新通知之间没有竞争。

3) 数据库(或实例)重启会使用一个 SqlNotificationInfo 值为 Restart 的信号来通知所有待处理的查询通知。了解更多关于 SqlDependency 和基于查询通知的内容,可以更好地理解。由于 SqlDependency 总是与数据库保持连接状态,因此在显式查询通知之前即可检测到数据库不可用情况。

4) 不是。稍后将详细介绍...

5) 没有“丢失的数据”。查询通知(因此包括 SqlDependency)从不通知您有关更改的具体信息,只通知您“已经”发生更改。您总是需要重新读取所有数据以查看发生了什么变化(并且我参考回答问题2)。一个新启动的应用程序还没有查询数据,因此没有更改可以通知。只有在首次查询数据后才能接收到通知。

从您的问题描述来看,我并不认为你需要查询通知。在我看来,您想要对任何更改做出反应,无论何时发生,即使您的应用程序没有运行。这当然不是缓存失效,而是变更跟踪。因此,您需要部署变更跟踪技术,如Change Data CaptureChange Tracking,两者都仅适用于SQL Server 2008及更高版本(不适用于SQL Server 2005)。在SQL Server 2005中,常见的做法是部署触发器并将消息排队给Service Broker来处理您正在尝试处理的相同问题(检测更改,对每个新数据行做出反应)。

关于你最后的一点,当应用程序启动时,它将查询所有数据以查看尚未处理的内容--与收到通知时相同。我认为我的问题描述可能不太准确--我认为我需要解决的问题与缓存之一完全相同,尽管与缓存无关。话虽如此,我将阅读你提供的所有链接并重新考虑我的方法。感谢你出色的回答。 - Phil Sandler
@Remus Rusanu,我读了您精彩的博客文章,但如果“当SQL Server 2005重新启动时,所有查询通知订阅都会被通知并结束”,那么它如何有用于缓存失效呢?似乎如果服务器控制订阅持续时间,那么就无法保证缓存一致性?我的使用情况是刷新Elastic Search索引。 - John Zabroski
1
服务器无法保证在实例离线期间没有更改数据。例如,管理员可能会复制并替换数据库文件。我建议您提出单独的问题。 - Remus Rusanu
@RemusRusanu完成 - http://stackoverflow.com/questions/34031454/updating-elastic-search-index-when-sql-server-table-changes 谢谢 - John Zabroski
我知道已经过了几年,但我只是想为其他人分享一下,SqlDependency似乎并不完全可靠,请阅读https://connect.microsoft.com/SQLServer/feedback/details/420996/avoid-false-positives-in-query-notifications-when-updating-unmonitored-columns。 - Jamo

5
从 .net 开发人员的角度来看,仅希望将其用于缓存失效,这真是一件痛苦的事情,并且它并不完全可靠。
特别是安装和故障排除方面,我们可以在一个环境中使其正常运行,但然后在另一个环境中无法正常工作。找出原因很困难且耗时。
即使一切都在运行,它也并不完全可靠。如果 SQL Server 负载过重,则可能会丢失通知,并且已知存在重新启动后通知未恢复的问题:http://connect.microsoft.com/SQLServer/feedback/details/543921/sqldependency-incorrect-behaviour-after-sql-server-restarts
如果有其他技术可以实现所需功能并且不易出错,那么最好避免使用此技术。

1
如果存在替代方案,使用替代方案会更好,你知道有什么替代方案吗? - Noctis
可能有点晚了,但你可以尝试访问https://github.com/dyatchenko/ServiceBrokerListener/issues。 - Choco

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接