5

I want to push the data from database to application instead of application pull the data. I have installed ms sql server and apache tomcat server. I have my application in apache tomcat, here I made connection to database. Now I want database send the data whenever there is update in data. But all I know is fetch the data from database is not good idea, because application needs to monitor the database for updated data will lead to fire the query for every 5 sec, this is not efficient as well.

I google it I got some answers they are Query Notification here, Sql server Agent Job to schedule the task automatically. If you have any other suggestion please post it.

4

1 回答 1

5

肯定有几种可能性可以做到这一点:

  • 实现不安全的 CLR 触发器
  • 实施不安全的 CLR 过程
  • 使用 xp_cmdshell
  • 调用网络服务
  • 使用查询通知

您可以在以下讨论中阅读一些关于它们的信息: Serial numbers, created and modified in SQL Server

就个人而言,我更喜欢查询通知而不是其他方法,因为它已经支持各种情况(例如同步/异步通信)并且您不必重新发明轮子。并且在您的情况下是 Microsoft 推荐的。

轮询是您提到的另一种方法。这是一种更像传统方法的方法,可能会有一些相关的性能损失,但如果你足够小心,你不应该担心它们。例如,如果您的应用程序中已经内置了身份验证,则可以在您的应用程序中创建另一列Users如果有与该用户相关的任何更改,则设置该表。然后,您的应用程序中可能只有一个线程每秒都会对该表执行一次查询(即使使用 NOLOCK 进行脏读也不应该成为问题)并维护一些内存结构(例如线程安全字典)这说明应该推送哪个客户端。另一个线程轮询您的字典,当它为客户端找到某些内容时,执行一个提取数据并将其发送到客户端的数据库查询。这看起来像是很多不必要的工作,但最后你会得到两个独立的工作人员,这在一定程度上有助于分离关注点;第一个只是执行“轻量级”数据库轮询的告密者;第二个提取真实数据并执行服务器推送。你甚至可以优化 push-worker 运行时的方式,它检查多个客户端是否需要一些数据,然后为所有需要它的人执行选择。您可能希望第二个工作人员的运行频率低于第一个工作人员。

编辑

如果您希望使用非 .NET 技术来实现相同的功能,则必须深入了解 SQL Server Service Broker。查询通知是在 .NET 中构建在 SQL Server Service Broker 之上的简化层,您必须自己构建该层的至少一部分。这包括在另一端使用 SEND 和 RECEIVE 创建队列、消息类型、服务和存储过程。您必须自己处理对话/对话。SB 实际上是一个经过调整以在 RDBMS 环境中工作的异步消息传递世界,因此您将看到一些新的 TSQL 表达式。但是,MSDN 可以提供帮助:

这也有帮助:从 Service Broker 外部激活非 .NET 应用程序

关于如何编码这些东西的示例:

-- First you have to enable SB for your database
USE master
ALTER DATABASE Playground
SET ENABLE_BROKER
GO

USE Playground
GO

-- Then create a message type; usually it will be XML
-- because it's very easy to serialize/deserialize it
CREATE MESSAGE TYPE [//Playground/YourMessageType]
VALIDATION = WELL_FORMED_XML
GO

-- Then create a contract to have a rule for communication
-- Specifies who sends which message type
CREATE CONTRACT [//Playground/YourContract] (
    [//Playground/YourMessageType] SENT BY ANY)
GO

--Creates queues, one for initiator (1) and one for target (2)
CREATE QUEUE MyQueue1
GO
CREATE QUEUE MyQueue2
GO

-- Finally, configure services that 'consume' queues
CREATE SERVICE [//Playground/YourService1]
ON QUEUE MyQueue1 ([//Playground/YourContract])
GO

CREATE SERVICE [//Playground/YourService2] 
ON QUEUE MyQueue2 ([//Playground/YourContract])
GO

-- Now you can send a message from service to service using contract
DECLARE 
    @dHandle uniqueidentifier,
    @Msg nvarchar(max) 

BEGIN DIALOG @dHandle
    FROM SERVICE [//Playground/YourService1]
    TO SERVICE '//Playground/YourService2'
    ON CONTRACT [//Playground/YourContract]
WITH ENCRYPTION = OFF

SELECT @Msg = (
    SELECT TOP 3 *
    FROM Table1
    FOR XML PATH('row'), ROOT('Table1'))

;SEND ON CONVERSATION @dHandle 
MESSAGE TYPE [//Playground/YourMessageType] (@Msg)

PRINT @Msg
GO

-- To get the message on the other end, use RECEIVE
-- Execute this in another query window
DECLARE @dHandle uniqueidentifier
DECLARE @MsgType nvarchar(128)
DECLARE @Msg nvarchar(max)

;RECEIVE TOP(1)
    @dHandle = conversation_handle,
    @Msg = message_body,
    @MsgType = message_type_name
FROM MyQueue2

SELECT @MsgType 
SELECT @Msg

END CONVERSATION @dHandle 
GO
于 2013-06-20T07:40:09.827 回答