本文将介绍sqlserver镜像监控中出现Oldest Unsent Transaction Threshold告警如何自愈


镜像监控的数据及告警由Database Mirroring Monitor Job作业进行记录及触发,当Oldest Unsent Transaction超过Threshold时,触发代码为32040的错误信息。


告警的出现可能跟主体服务器实例和镜像服务器实例中的负载及它们的网络连接相关(博主在维护中遇到的情况大多是这样),但是在负载或网络连接恢复正常后,Oldest Unsent Transaction告警信息依然持续出现,直到backup database或者backup log后,告警才消失。


关于这个问题可在以下连接查看相关详细信息

Spurious Oldest Unsent Transaction alerts for database mirroring


从实例日志中可知告警信息如下:

The alert for 'oldest unsent transaction' has been raised. The current value of '35' surpasses the threshold '30'.


如果是只有一个数据库配置镜像,那么很容易定位出现告警的数据库;如果是多个数据库配置镜像,从告警信息中,我们无法得知到底是哪个数据库出现告警。


那么,实现自愈难点:

1. 告警数据是哪个

2. 如何计算oldest unsent transaction


通过分析Database Mirroring Monitor Job,我们可以知道Oldest Unsent Transaction告警的出现是由于sys.database_mirroring表的end_of_log_lsn与mirroring_failover_lsn之间相差较大,在Database Mirroring Monitor Job作业中进行Oldest Unsent Transaction计算时结果超出了Threshold,因此触发告警。


我们先总结一下:

(1) 告警是由于sys.database_mirroring表的end_of_log_lsn与mirroring_failover_lsn之间相差较大导致

(2) Database Mirroring Monitor Job作业能分析并得知是哪个数据库告警

(3) backup database、backup log后告警会消失


如何获取告警时的数据库名,有2种方法:

1. 改写Database Mirroring Monitor Job作业中相关的存储过程,自定义错误代码及信息

可参考SQL Sentry(SQL哨兵)的技术支持Steve Wright的博客,有详细的改写代码


2. 提取Database Mirroring Monitor Job作业中相关代码进行改写,自定义代码段进行获取数据

(1)建表

(2)收集数据

SQLServer:镜像监控之oldest unsent transaction告警自愈_第1张图片



获取到告警相关数据后,我们就可以开始制定相关的“自愈”方案


先决条件(可根据实际情况添加):

1. 主体与镜像连接正常

select 

database_id,mirroring_role,mirroring_role_desc,

mirroring_state,mirroring_state_desc,

mirroring_partner_instance,mirroring_partner_name 

from sys.database_mirroring 

where database_id=@database_id


2. 主体无长事务正在运行

--查询执行时长超过dbm_monitor_alerts表time_behind阈值的事务

declare @database_id int

declare @time_behind int

set @database_id=5

select @time_behind=time_behind from msdb..dbm_monitor_alerts where database_id=@database_id

select count(1) as long_transactions_count from sys.dm_tran_database_transactions dt,sys.dm_tran_active_transactions st

where dt.transaction_id=st.transaction_id

and dt.database_id=@database_id

and DATEDIFF(minute, st.transaction_begin_time, GETDATE())>@time_behind 


3. 无备份在运行

SELECT *

FROM sys.dm_exec_requests AS er  

WHERE er.database_id=@database_id 

and er.command in ('BACKUP LOG','BACKUP DATABASE')


根据先决条件写成Oldest Unsent Transaction告警自愈脚本



部署方式:

1. 创建Sql Agent Alerts监控错误代码:32040,在Response选项中设置Execute Job为镜像告警处理作业

2. 在镜像告警处理作业中第1步为收集数据,第2步为告警自愈


至此,Oldest Unsent Transaction告警自愈已实现,根据实际监控情况进行相关细节的优化