队列停止(禁用)没有任何有害消息

时间:2011-01-26 17:29:22

标签: sql-server sql-server-2005 service-broker

我的队列在没有任何明显原因的情况下停止,在此队列中我实现了 posion消息处理。在处理过程中,它会记录并丢弃任何有害信息。

它已经工作了一年多而没有停止。但最近(问题在四周前开始),它每周停止一次或两次。仅在本周它停了两次。

当我用新的中毒消息检查表时,没有!当我启用队列时,处理成功恢复,并且“毒性消息”情况不会重现。

关于队列的任务:每天接收大约2-3000条消息。它用于在事务外部运行存储过程。并且每条消息可以持续一点处理(进行大量选择,插入,更新)。

让我解释一下:数据库具有在事务内部触发的触发器,触发器发送消息以在触发器外部运行某些代码。异步行为可防止丢弃数据库的性能。

我已经检测到即使在处理消息时发生死锁,队列也会将消息视为中毒。所以原则上它不应该是性能问题。但是,它可以吗?也许数据库正在增长,而且处理消息的时间太长了?

但是,如果没有检测到它是什么,我怎么能找到它呢? 为什么队列停止的其他原因? 如何保存队列被禁用的时间和消息? 有没有人知道如何进行任何取证分析? 有什么想法吗?

<小时/> 更新暴露解决方案:
根据Remus的帖子,我尝试使用事件通知来获取队列停止的确切时刻。

CREATE EVENT NOTIFICATION [QueueDisabledEN]
  ON QUEUE [dbo].[ProcessQueue]
  FOR BROKER_QUEUE_DISABLED
  TO SERVICE 'Queue Watch Service', 'current database';

然后检查事件日志:

select * from sys.event_notificiation

但是,由于很难知道事件发生的环境,(在妈妈们还在运行什么?),法医分析就此结束了。幸运的是,我的代理服务实现存储了包含发货日期,收货日期,日期处理等的消息......这有助于我检测到在3秒内队列中充斥着数百条消息,这些消息需要很长时间才能处理

虽然我找到了一个真正的解决方案,但唯一的临时解决方案是每x分钟检查一次代理作业队列的状态并启用它:

IF (EXISTS(SELECT * FROM sys.service_queues WHERE name like 'ProcessQueue' AND (is_receive_enabled = 0 OR is_enqueue_enabled = 0))) BEGIN
    PRINT convert(nvarchar, getdate(), 121)+ ': Activando la cola ProcessQueue'
    ALTER QUEUE ProcessQueue WITH STATUS = ON 
END

感谢Remus!

1 个答案:

答案 0 :(得分:4)

当您发现队列处于禁用状态并且启用了队列时,我认为处理成功恢复并且“毒性消息”情况不会重现。这表明原因是暂时的或与时间有关。它可能是正在运行的SQL代理作业,并导致队列处理死锁,从而迫使队列处理回滚。根据我的经验,死锁是最典型的毒药信息原因。您最好的取证工具是系统事件日志,因为激活的过程会将错误输出到ERRORLOG中,从而输出到系统事件日志中。

每当毒性消息触发器禁用队列(连续5次回滚)时,就会触发{QUEUE_DISABLED类型的event notification。您可以在处理此事件时捕获更多取证信息,因为它将在队列被禁用后不久运行。

作为旁注,你永远不能拥有真正的“毒药信息处理”。每当您增强处理某些错误情况的处理时,“有害消息”的定义将变为能够禁用新错误处理的消息