对处于恢复状态的可用性组数据库进行故障排除
一、什么是恢复状态?
当辅助服务器必须撤消其已应用的更改才能恢复与主服务器同步时,就会发生恢复状态。
可用性组主副本和辅助副本在正常操作期间保持连接状态,以便主副本上的更改主动与辅助副本同步。
在故障转移期间,此连接状态将被切断。一旦新的主副本上线,主副本和辅助副本之间就会重新建立连接。在此初始连接状态期间,会协商一个公共恢复点,新的辅助设备应在该恢复点开始恢复,以便与主设备同步。
如果故障转移时正在运行大型事务,则新的辅助数据库日志将领先于主副本数据库。协商的新公共恢复点将要求辅助副本从主副本接收页面,以便使其处于可以恢复同步的状态。恢复过程也称为“撤消重做”。
恢复过程本质上很慢,经常发生,并且通常触发恢复状态的小事务很难被注意到。当故障转移中断大型事务时,通常会注意到恢复状态,导致许多页面从主数据库发送到辅助数据库,以将辅助副本数据库恢复到可恢复状态。
二、可用性组数据库处于恢复状态的症状和影响
当数据库在辅助副本上处于恢复状态时,数据库不会同步,因此不会从主副本接收更改。主副本上的数据库突然丢失可能会导致数据丢失。
三、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) 对象资源管理器连接到辅助副本,并深入查看Management、Extended Events和Sessions。右键单击AlwaysOn_health事件并选择“观看实时数据”。您应该会看到一个新的选项卡式窗口,报告恢复操作的当前状态。通过事件每五分钟报告一次状态hadr_trace_message
,并报告恢复操作的完成百分比。
说明:
扩展事件hadr_trace_message
已添加到 SQL Server 中的最新累积更新中。您必须运行最新的累积更新才能在AlwaysOn_health
扩展事件会话中观察此扩展事件。
在估计恢复完成情况时,辅助副本上的 SQL Server 错误日志没有太大帮助。从下图中可以观察到,从10:08到11:03,在恢复状态下,几乎没有什么报告。一旦辅助副本接收到来自主副本的所有页面,它现在就可以回滚在触发恢复状态的原始主副本上运行的事务。恢复时间为11:03至11:05。恢复完成后不久,数据库应开始与主副本同步,并在辅助数据库处于恢复状态时赶上主副本上所做的所有更改。
五、如何解决失败的只读工作负载
由于恢复中的辅助副本数据库无法访问,只读工作负载会失败。更新读取意图路由表以将流量路由回主副本或另一个辅助副本,直到受影响的辅助副本数据库完成恢复过程。
恢复状态 - 监视大事务
如果您在计划的故障转移期间经常观察到此状态,请实施一个在故障转移之前检查大型事务的过程。以下查询报告系统上任何打开的事务的事务开始时间和当前时间,并提供事务的输入缓冲区。
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
微信赞赏
支付宝赞赏