如何将数据从数据库推送到应用程序?

时间:2013-06-20 07:21:00

标签: sql-server database tomcat query-notifications

我想将数据从数据库推送到应用程序而不是应用程序提取数据。我已经安装了ms sql server和apache tomcat server。我在apache tomcat中有我的应用程序,这里我连接到数据库。现在我希望数据库在数据更新时发送数据。但我所知道的是从数据库中获取数据并不是一个好主意,因为应用程序需要监视数据库中的更新数据会导致每隔5秒触发一次查询,这样效率也不高。

我谷歌它得到了一些答案,他们是查询通知here,Sql server Agent Job自动安排任务。如果您有任何其他建议,请发布。

1 个答案:

答案 0 :(得分:4)

肯定有几种可能性:

  • 实施不安全的CLR触发器
  • 实施不安全的CLR程序
  • 使用xp_cmdshell
  • 致电网络服务
  • 使用查询通知

您可以在此讨论中阅读一些有关它们的内容: Serial numbers, created and modified in SQL Server

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

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

修改

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

这也有帮助:Externally activate non-.NET application from Service Broker

如何编写内容的示例:

-- 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