我有一个没有任何明显原因的队列,在这个队列中我实现了一个位置消息处理。在处理过程中,它会记录并丢弃任何有害消息。
它运行良好一年多没有停止。但是最近(问题开始于四个星期前),它每周停止一次或两次。仅在本周它停止了两次。
而当我检查带有新中毒消息的表格时,没有!当我启用队列时,处理成功恢复并且“毒消息”情况不会重现。
关于队列的任务:每天大约接收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
谢谢莱姆斯!