我在SQL2005数据库中有一个负载很重的表(许多插入/更新/删除).我想尽可能接近实时地对所有这些更改进行一些后期处理(异步以便不以任何方式锁定表).我看了很多可能的解决方案,但似乎无法找到一个感觉正确的整洁解决方案.
后期处理的类型也相当繁重,以至于Windows侦听器服务实际上将处理传递给许多机器.然而,应用程序的这部分已经启动并运行,完全异步,而不是我需要帮助 - 我只是想提及这只是因为它影响设计决策,因为我们不能只加载一些CLR对象DB完成处理.
所以,简单的问题仍然存在:表中的数据更改,我想在远程服务器上的c#代码中进行一些处理.
目前我们已经提出使用一个sql触发器,它执行"xp_cmdshell"来启动一个引发windows服务正在侦听的事件的exe.这只是感觉很糟糕.
但是,我在网上看到的其他解决方案也让人感到相当费解.例如,设置SQLCacheDependancy还涉及必须设置Service Broker.另一个可能的解决方案是使用CLR触发器,它可以调用Web服务,但是这里有很多关于它的警告,这是一个糟糕的方法,尤其是在性能至关重要时.
理想情况下,我们不会对表格进行更改,而是会拦截我们的应用程序中的调用并从那里通知服务,遗憾的是,虽然我们有一些遗留应用程序也会对数据进行更改,并且监视表格是唯一的集中位置此时此刻.
非常感激任何的帮助.
摘要:
需要实时响应表数据的变化
表现至关重要
预计会有大量的流量
轮询和计划任务不是一种选择(或实时)
实施服务代理太大(但可能只是解决方案?)
CLR代码尚未排除,但如果建议则需要执行
监听器/监视器可能是远程机器(可能是相同的物理网络)
Remus Rusanu.. 19
您真的没有那么多方法来检测SQL 2005中的更改.您已经列出了大部分内容.
查询通知.这是为SqlDependency及其衍生产品提供支持的技术,您可以阅读有关The Mysterious Notification的更多详细信息.但QN旨在使结果无效,而不是主动通知更改内容.您只会知道该表有更改,而不知道更改了什么.在繁忙的系统上,这将无法正常工作,因为通知将会不断发生.
日志阅读.这是事务复制使用的,也是检测更改的最少侵入性方法.不幸的是,仅适用于内部组件.即使您设法了解日志格式,问题在于您需要引擎支持将日志标记为"正在使用",直到您阅读它,否则它可能会被覆盖.只有事务复制才能执行此类特殊标记.
数据比较.依靠时间戳列来检测更改.也是基于拉力,非常具有侵略性并且在检测删除方面存在问题.
应用层.这是理论上的最佳选择,除非应用程序范围之外的数据发生变化,在这种情况下它会崩溃.实际上,在应用程序范围之外总会发生变化.
触发器.最终,这是唯一可行的选择.基于触发器的所有更改机制都以相同的方式工作,它们将更改通知排队到监视队列的组件.
总是建议做一个紧密耦合的同步通知(通过xp_cmdshell,xp_olecreate,CLR,通知WCF,你给它命名),但所有这些方案在实践中都失败了,因为它们存在根本缺陷:
- 它们不考虑事务的一致性和回滚
- 它们引入了可用性依赖性(除非通知的组件在线,否则OLTP系统无法继续)
- 它们执行得非常糟糕,因为每个DML操作都必须等待某种形式的RPC调用才能完成
如果触发器实际上没有主动通知侦听器,但只排队通知,则监视通知队列时出现问题(当我说'队列'时,我的意思是任何充当队列的表).监控意味着拉动队列中的新条目,这意味着正确地平衡检查频率和更改负载,并对负载峰值做出反应.这根本不是微不足道的,实际上非常困难.但是,在SQL服务器中有一个语句具有阻止语义,无需拉动,直到更改变为可用:WAITFOR(RECEIVE).这意味着Service Broker.你在帖子中多次提到过SSB,但是你是非常正确的,因为很大的未知因素而害怕部署SSB.但实际情况是,到目前为止,它最适合您描述的任务.
您不必部署完整的SSB体系结构,其中通知一直传递到远程服务(无论如何都需要远程SQL实例,甚至是Express实例).您需要共同的就是从发送通知的那一刻起(在提交更改之后)解耦检测到更改的时刻(DML触发器).为此,您需要的是本地SSB队列和服务.在触发器中,您向本地服务发送更改通知.在原始DML事务提交之后,服务过程激活并传递通知,例如使用CLR.您可以在Asynchronous T-SQL中看到与此类似的示例.
如果你沿着这条路走下去,你需要学习一些技巧来实现高吞吐量,你必须理解SSB中有序传递消息的概念.我推荐你阅读这些链接:
重用对话
编写服务代理程序
SQL Connections 2007演示
关于检测更改的方法,SQL 2008 显然添加了新选项:更改数据捕获和更改跟踪.我强调'显然',因为它们不是真正的新技术.CDC使用日志阅读器并基于现有的事务复制机制.CT使用触发器,与现有的Merge复制机制非常相似.它们都适用于偶尔连接的系统,这些系统需要同步,因此不适合实时更改通知.他们可以填充更改表,但是您可以使用任务来监视这些表以进行更改,这完全取决于您从何处开始.
您真的没有那么多方法来检测SQL 2005中的更改.您已经列出了大部分内容.
查询通知.这是为SqlDependency及其衍生产品提供支持的技术,您可以阅读有关The Mysterious Notification的更多详细信息.但QN旨在使结果无效,而不是主动通知更改内容.您只会知道该表有更改,而不知道更改了什么.在繁忙的系统上,这将无法正常工作,因为通知将会不断发生.
日志阅读.这是事务复制使用的,也是检测更改的最少侵入性方法.不幸的是,仅适用于内部组件.即使您设法了解日志格式,问题在于您需要引擎支持将日志标记为"正在使用",直到您阅读它,否则它可能会被覆盖.只有事务复制才能执行此类特殊标记.
数据比较.依靠时间戳列来检测更改.也是基于拉力,非常具有侵略性并且在检测删除方面存在问题.
应用层.这是理论上的最佳选择,除非应用程序范围之外的数据发生变化,在这种情况下它会崩溃.实际上,在应用程序范围之外总会发生变化.
触发器.最终,这是唯一可行的选择.基于触发器的所有更改机制都以相同的方式工作,它们将更改通知排队到监视队列的组件.
总是建议做一个紧密耦合的同步通知(通过xp_cmdshell,xp_olecreate,CLR,通知WCF,你给它命名),但所有这些方案在实践中都失败了,因为它们存在根本缺陷:
- 它们不考虑事务的一致性和回滚
- 它们引入了可用性依赖性(除非通知的组件在线,否则OLTP系统无法继续)
- 它们执行得非常糟糕,因为每个DML操作都必须等待某种形式的RPC调用才能完成
如果触发器实际上没有主动通知侦听器,但只排队通知,则监视通知队列时出现问题(当我说'队列'时,我的意思是任何充当队列的表).监控意味着拉动队列中的新条目,这意味着正确地平衡检查频率和更改负载,并对负载峰值做出反应.这根本不是微不足道的,实际上非常困难.但是,在SQL服务器中有一个语句具有阻止语义,无需拉动,直到更改变为可用:WAITFOR(RECEIVE).这意味着Service Broker.你在帖子中多次提到过SSB,但是你是非常正确的,因为很大的未知因素而害怕部署SSB.但实际情况是,到目前为止,它最适合您描述的任务.
您不必部署完整的SSB体系结构,其中通知一直传递到远程服务(无论如何都需要远程SQL实例,甚至是Express实例).您需要共同的就是从发送通知的那一刻起(在提交更改之后)解耦检测到更改的时刻(DML触发器).为此,您需要的是本地SSB队列和服务.在触发器中,您向本地服务发送更改通知.在原始DML事务提交之后,服务过程激活并传递通知,例如使用CLR.您可以在Asynchronous T-SQL中看到与此类似的示例.
如果你沿着这条路走下去,你需要学习一些技巧来实现高吞吐量,你必须理解SSB中有序传递消息的概念.我推荐你阅读这些链接:
重用对话
编写服务代理程序
SQL Connections 2007演示
关于检测更改的方法,SQL 2008 显然添加了新选项:更改数据捕获和更改跟踪.我强调'显然',因为它们不是真正的新技术.CDC使用日志阅读器并基于现有的事务复制机制.CT使用触发器,与现有的Merge复制机制非常相似.它们都适用于偶尔连接的系统,这些系统需要同步,因此不适合实时更改通知.他们可以填充更改表,但是您可以使用任务来监视这些表以进行更改,这完全取决于您从何处开始.