对处于恢复状态的可用性组数据库进行故障排除

发布时间 2023-07-29 11:49:02作者: 雪竹子

一、什么是恢复状态?

当辅助服务器必须撤消其已应用的更改才能恢复与主服务器同步时,就会发生恢复状态。

可用性组主副本和辅助副本在正常操作期间保持连接状态,以便主副本上的更改主动与辅助副本同步。

在故障转移期间,此连接状态将被切断。一旦新的主副本上线,主副本和辅助副本之间就会重新建立连接。在此初始连接状态期间,会协商一个公共恢复点,新的辅助设备应在该恢复点开始恢复,以便与主设备同步。

如果故障转移时正在运行大型事务,则新的辅助数据库日志将领先于主副本数据库。协商的新公共恢复点将要求辅助副本从主副本接收页面,以便使其处于可以恢复同步的状态。恢复过程也称为“撤消重做”。

恢复过程本质上很慢,经常发生,并且通常触发恢复状态的小事务很难被注意到。当故障转移中断大型事务时,通常会注意到恢复状态,导致许多页面从主数据库发送到辅助数据库,以将辅助副本数据库恢复到可恢复状态。

二、可用性组数据库处于恢复状态的症状和影响

当数据库在辅助副本上处于恢复状态时,数据库不会同步,因此不会从主副本接收更改。主副本上的数据库突然丢失可能会导致数据丢失。

三、Always On 仪表板报告主数据库上未同步

对可用性组进行故障转移后,您可能会发现辅助可用性组报告为未同步,而故障转移成功。Always On 仪表板报告主数据库上的“未同步”和辅助数据库上的“正在恢复” 。

Always On 仪表板报告主数据库上未同步始终在线仪表板报告 在辅助设备上恢复
Always On 仪表板报告主数据库上未同步的屏幕截图。 Always On 仪表板报告在辅助设备上恢复的屏幕截图。

当您在主数据库上查询以下 Always On 可用性组 (AG) 动态管理视图 (DMV) 时,数据库处于NOT SYNCHRONIZING状态。

SELECT DISTINCT ar.replica_server_name, drcs.database_name, drs.database_id, drs.synchronization_state_desc, drs.database_state_desc
FROM sys.availability_replicas ar 
JOIN sys.dm_hadr_database_replica_states drs 
ON ar.replica_id=drs.replica_id 
JOIN sys.dm_hadr_database_replica_cluster_states drcs
ON drs.group_database_id=drcs.group_database_id

  

 当您在辅助数据库上查询 DMV 时,可用性组数据库处于REVERTING状态。

 

四、估计恢复状态剩余时间

使用以下方法之一来估计恢复状态的剩余时间:

使用 AlwaysOn_health XEvent 会话

AlwaysOn_health扩展事件诊断日志有一个hadr_trace_message事件,该事件每五分钟报告一次恢复状态进度。

使用 SQL Server Management Studio (SSMS) 对象资源管理器连接到辅助副本,并深入查看ManagementExtended EventsSessions右键单击AlwaysOn_health事件并选择“观看实时数据”您应该会看到一个新的选项卡式窗口,报告恢复操作的当前状态。通过事件每五分钟报告一次状态hadr_trace_message,并报告恢复操作的完成百分比。

 笔记

扩展事件hadr_trace_message已添加到 SQL Server 中的最新累积更新中。您必须运行最新的累积更新才能在AlwaysOn_health扩展事件会话中观察此扩展事件。

AlwaysOn_health 扩展事件诊断日志的屏幕截图。

在估计恢复完成情况时,辅助副本上的 SQL Server 错误日志没有太大帮助。从下图中可以观察到,从10:0811:03,在恢复状态下,几乎没有什么报告。一旦辅助副本接收到来自主副本的所有页面,它现在就可以回滚在触发恢复状态的原始主副本上运行的事务。恢复时间为11:0311:05恢复完成后不久,数据库应开始与主副本同步,并在辅助数据库处于恢复状态时赶上主副本上所做的所有更改。

还原和恢复阶段的 SQL Server 错误日志的屏幕截图。

 

五、如何解决失败的只读工作负载

由于恢复中的辅助副本数据库无法访问,只读工作负载会失败。更新读取意图路由表以将流量路由回主副本或另一个辅助副本,直到受影响的辅助副本数据库完成恢复过程。

恢复状态 - 监视大事务

如果您在计划的故障转移期间经常观察到此状态,请实施一个在故障转移之前检查大型事务的过程。以下查询报告系统上任何打开的事务的事务开始时间和当前时间,并提供事务的输入缓冲区。

SELECT tat.transaction_begin_time, getdate() AS 'current time', es.program_name, es.login_time, es.session_id, tst.open_transaction_count, eib.event_info
FROM sys.dm_tran_active_transactions tat
JOIN sys.dm_tran_session_transactions tst ON tat.transaction_id=tst.transaction_id
JOIN sys.dm_exec_sessions es ON tst.session_id=es.session_id 
CROSS APPLY sys.dm_exec_input_buffer(es.session_id, NULL) eib WHERE es.is_user_process = 1
ORDER BY tat.transaction_begin_time ASC