我有一个在SQL2005数据库重负载(许多插入/更新/删除)的表。 我想所有这些变化为接近实时地做一些后期处理(异步从而不以任何方式锁定表)。 我看了一些可能的解决方案,但似乎无法找到一个巧妙的解决办法感觉不错。
那种后期处理是相当沉重的为好,以至于Windows监听服务实际上是要在经过处理的数量的机器。 但是这个应用程序的一部分是已经投入运行,completetly异步,而不是我需要帮助 - 我只是想简单地提到这一点,因为它影响的是设计决定,我们不能只加载了一些CLR对象中DB来完成处理。
因此,简单的问题依然存在:表中的数据变化,我想要做的在C#代码一些处理的远程服务器上。
目前我们已经想出了使用SQL触发器,它执行“xp_cmdshell的”劳克这引起了该窗口服务侦听事件的exe文件。 这只是感觉不好。
不过,我已经看了网上的感觉其他的解决方案,而令人费解了。 例如设置SQLCacheDependancy还涉及必须设置服务的经纪人。 另一种可能的解决方案是使用一个CLR触发器,它可以调用Web服务,但网上有一个关于它是一个糟糕的方式去了解它,尤其是当性能是至关重要的这么多的警告。
Idealy我们不会depnd在桌子上的变化,但宁愿从那里拦截我们的应用程序内调用,并通知服务,但遗憾的是我们有一些遗留的应用程序在更改过的数据和监控表是唯一集中的地方在此时此刻。
非常感激任何的帮助。
摘要:
- 需要实时表中的数据变化作出反应
- 性能是关键
- 交通的高容量有望
- 轮询和计划的任务是不是一种选择(或实时)
- 实现服务代理太大(但可能是唯一的解决办法?)
- CLR代码尚未排除,但如果需要建议被perfomant
- 听众/监视器可以是远程机器(可能是相同phyisical网络)
你真的没有很多的方法来检测SQL 2005年的变化你已经列出了一大半。
查询通知 。 这是权力的SqlDependency及其衍生物,你可以阅读更多的细节技术神秘的通知 。 但QN设计为无效结果,而不是积极主动地通知更改内容。 你只知道表中有变化,不知道是什么改变了。 在繁忙系统上,这将无法工作,因为通知会相当多汽车无。
登录阅读 。 这是事务性复制使用,并及时发现变化最小侵入性的方式。 遗憾的是仅提供给内部组件。 即使你设法了解日志格式,问题是,你从发动机需要支持日志标记为“使用中”,直到你读它,或者它可能会被覆盖。 只有事务复制可以做这样的特殊标记。
数据进行比较 。 依靠时间戳列检测的变化。 同样是基于拉,相当intrussive和有问题检测删除。
应用层 。 这在理论上是最佳的选择,除非有变化存在的对应用程序的范围之外的数据,在这种情况下,它崩溃。 在实践中总会有改变应用程序的范围之外存在的。
触发 。 归根结底,这是唯一可行的选择。 基于触发器的所有变化机制的工作方式相同,他们排队的变更通知到监控队列中的组成部分。
总有一些建议,做一个紧耦合的同步通知(通过xp_cmdshell的,xp_olecreate,CLR,通知与WCF,你的名字),而是因为它们是根本性的缺陷所有这些方案在实践中失败:
- 他们不考虑交易的一致性和回滚
- 他们引进的可用性依赖(OLTP系统无法进行,除非该通知的成分是在线)
- 他们可怕的执行,因为每个DML操作必须等待某种形式的RPC调用完成
如果触发实际上不主动通知监听器,但只能排队等候通知,有监察通知队列中的问题(当我说“排队”,我的意思是作为一个队列中的所有表)。 监控意味着在队列中拉出用于新条目,这意味着与变化的负载平衡正确检查的频率,并进行反应以加载尖峰。 这不是在所有的小事,其实是非常困难的。 然而,在具有语义块,不拉,直到变化变为可用SQL服务器的一个声明: WAITFOR(接收) 。 这意味着服务代理。 您在您的文章中提到SSB几次,但你是,那么rightfuly,害怕因为大未知的部署它的。 但现实是,它是,到目前为止,你所描述的任务最合适的。
您没有部署一个完整的SSB结构中,其中notificaition被一路传递到远程服务(即无论如何都会需要一个远程SQL实例,即使是表达一种)。 所有你需要帮凶在检测到变化时(DML触发器)的那一刻时通报交付(变更将提交后)脱钩的时刻。 对于这一切,你需要的是一个本地SSB队列和服务。 在触发你发送一个变化通知到本地服务。 原来的DML事务提交后,服务程序启动 ,并提供通知,使用CLR例如。 你可以看到在类似于这样的例子异步T-SQL 。
如果你走这条路有一些你需要学习,以实现高吞吐量的技巧和你一定understant从国家统计局的消息的有序传递的概念。 我reommend你读这些链接:
- 重用对话
- 编写服务代理程序
- SQL连接2007演示
关于手段来检测更改,SQL 2008 显然是增加了新的选项: 变化数据捕捉和变更跟踪 。 我强调“显然”,因为他们不是真正的新技术。 CDC使用日志读取,并基于现有的事务复制机制。 CT使用触发器和非常类似于现有的合并复制机制。 它们都适用于需要保持同步,因此不appropiate实时变化通知偶尔连接系统。 他们可以填充变更表,但你会留下来监控这些表更改的任务,而这正是从你开始的地方。
这可以在许多方面进行。 下面的方法,因为你不想使用CLR触发器和SQLCMD选项很简单。
编辑:
我认为微软ADO.Net同步服务,可以为你工作。 看看下面的链接。 它可以帮助你
- 如何:使用SQL Server更改跟踪- SQL Server 2008中
- 使用自定义的更改跟踪系统-下面的SQL Server 2008
在类似的情况下,我们使用的是写消息队列(MSMQ)CLR触发。 用C#编写服务正在监视队列和做后期处理。 在我们的情况下,它都做在同一台服务器上,但您可以直接发送这些消息发送到远程队列,在不同的机器上,完全绕过“本地监听”。
从触发调用的代码如下所示:
public static void SendMsmqMessage(string queueName, string data)
{
//Define the queue path based on the input parameter.
string QueuePath = String.Format(".\\private$\\{0}", queueName);
try
{
if (!MessageQueue.Exists(QueuePath))
MessageQueue.Create(QueuePath);
//Open the queue with the Send access mode
MessageQueue MSMQueue = new MessageQueue(QueuePath, QueueAccessMode.Send);
//Define the queue message formatting and create message
BinaryMessageFormatter MessageFormatter = new BinaryMessageFormatter();
Message MSMQMessage = new Message(data, MessageFormatter);
MSMQueue.Send(MSMQMessage);
}
catch (Exception x)
{
// async logging: gotta return from the trigger ASAP
System.Threading.ThreadPool.QueueUserWorkItem(new WaitCallback(LogException), x);
}
}
既然你说,是在该表上运行许多插入,批处理会更适合。
为什么刚刚创建计划作业,这在大块处理由标志列,确定新的数据和处理数据?
使用典型的触发器引发的数据库的CLR。 这CLR才会开始远程使用Win32_Process类的程序:
http://motevich.blogspot.com/2007/11/execute-program-on-remote-computer.html