一、开篇唠唠:为什么你的Always On总出问题?

作为SQL Server最常用的高可用方案之一,Always On可用性组通过多副本同步实现故障自动转移。但实际操作中,数据库管理员常常会遇到这些让人头疼的场景:

  • 副本突然变成"Synchronizing"状态,进度条卡住几小时不动
  • 日志传送队列堆积如山,主副本和辅助副本数据差出天际
  • 日常巡检发现同步延迟暴涨,系统警报响个不停

上个月笔者就遇到一个生产案例:某电商平台的订单库突然停摆,查了半小时才发现是辅助副本同步中断导致主副本被锁死。下面将通过真实案例拆解故障处理全流程,并附上"救命级"排查脚本。


二、故障现象快速定位:你的副本究竟出了什么问题?

① 副本挂起的典型症状

-- 查询同步状态(所有副本通用)
SELECT 
    ag.name AS [AG Name],
    ar.replica_server_name AS [Replica],
    drs.database_id AS [DB ID],
    drs.synchronization_state_desc AS [Sync State],
    drs.synchronization_health_desc AS [Health State]
FROM sys.dm_hadr_database_replica_states drs
JOIN sys.availability_replicas ar ON drs.replica_id = ar.replica_id
JOIN sys.availability_groups ag ON ag.group_id = ar.group_id
WHERE drs.is_local = 1;

当输出中看到某个副本长时间停留在SYNCHRONIZING状态,且健康状态为NOT_HEALTHY时,说明同步进程已卡死。

② 同步中断的特征表现

-- 检查日志发送队列(在主副本执行)
SELECT 
    database_name,
    log_send_queue_size AS [Log KB Pending],
    log_send_rate AS [KB/sec]
FROM sys.dm_hadr_database_replica_states
WHERE is_local = 1;

-- 检查重做队列(在辅助副本执行) 
SELECT 
    database_name,
    redo_queue_size AS [Redo KB Pending],
    redo_rate AS [KB/sec]
FROM sys.dm_hadr_database_replica_states
WHERE is_local = 1;

如果队列持续增长且传输速率接近于零,证明日志传送链路出现阻塞。


三、救命实操:同步卡死的紧急处理步骤

场景重现:某金融系统在周五业务高峰期出现副本挂起,错误日志显示Error 35250: The connection to the primary replica is not active.

① 应急处理流程

-- 步骤1:强制故障转移(在灾难性场景中使用)
ALTER AVAILABILITY GROUP [AG_Finance] FAILOVER;

-- 步骤2:暂停并恢复同步(推荐先尝试此操作)
ALTER DATABASE [FinanceDB] SET HADR SUSPEND;
ALTER DATABASE [FinanceDB] SET HADR RESUME;

-- 步骤3:重置副本端点(解决网络问题后)
ALTER ENDPOINT [Hadr_endpoint] STATE = STOPPED;
ALTER ENDPOINT [Hadr_endpoint] STATE = STARTED;

② 深度排查脚本

-- 检查网络延迟(跨副本执行)
SELECT
    r.replica_server_name,
    r.endpoint_url,
    c.connection_connect_time_ms,
    c.connection_flow_control_time_ms
FROM sys.dm_hadr_availability_replica_cluster_nodes r
JOIN sys.dm_hadr_availability_replica_cluster_states c
ON r.replica_id = c.replica_id;

-- 定位阻塞会话
SELECT
    session_id,
    command,
    blocking_session_id,
    wait_type,
    wait_time
FROM sys.dm_exec_requests
WHERE command LIKE '%HADR%';

四、防患未然:这些配置错误你中招了吗?

① 日志文件设置不当

-- 错误案例:主副本日志文件自动增长设为默认值
ALTER DATABASE [OrderDB] MODIFY FILE (
    NAME = N'OrderDB_log',
    MAXSIZE = 2048GB,  -- 必须预留足够空间
    FILEGROWTH = 1024MB -- 禁止使用百分比增长
);

② 端点认证配置错误

New-SqlHadrEndpoint -Name "Hadr_endpoint" -Port 5022 
                    -EncryptionAlgorithm Aes -EncryptionRequired
                    -Certificate "AG_Certificate"

③ 网络带宽分配误区

-- 错误的带宽限制设置
ALTER AVAILABILITY GROUP [AG_Web]
MODIFY REPLICA ON 'Node02' WITH (
    PRIMARY_ROLE (ALLOW_CONNECTIONS = READ_WRITE ),
    SECONDARY_ROLE (ALLOW_CONNECTIONS = READ_ONLY ),
    SESSION_TIMEOUT = 10,  -- 超时过短会导致误判
    CONNECTION_MODE = DISCONNECT_ONLY
);

五、关联技术实战:日志压缩与网络优化

① 启用日志压缩(SQL Server 2016+)

ALTER AVAILABILITY GROUP [AG_Web]
MODIFY REPLICA ON 'Node02' WITH (COMPRESSION = ON);

-- 监控压缩效率
SELECT 
    compression_rate = 
        (compressed_bytes / NULLIF(uncompressed_bytes,0)) * 100,
    last_compressed_time
FROM sys.dm_hadr_physical_seeding_stats;

② 网络带宽优先级设置(Windows Server 2019+)

# 为Always On流量分配专用带宽
New-NetQosPolicy -Name "AG_Traffic" -IPDscp 46 
                -AppPathNameMatchCondition "sqlservr.exe" 
                -ThrottleRateActionBitsPerSecond 1Gb

六、应用场景与经验总结

典型应用场景

  • 金融行业:需要RPO=0的跨机房容灾
  • 电商系统:大促期间实现读写分离负载均衡
  • 医疗系统:满足HIPAA法规的数据冗余要求

技术优缺点分析
✅ 优点:故障切换秒级完成,支持多副本异地部署
❌ 缺点:配置复杂度高,网络依赖性强

必知的注意事项

  1. 永远在主副本执行DDL操作
  2. 监控日志增长速率与磁盘空间
  3. 定期验证故障转移流程
  4. 使用透明数据加密时必须同步证书