一、为什么要搞自动故障转移?

某天夜里2点,我刚躺下就被生产环境的告警震醒。主数据库所在的物理机突然宕机,业务系统瞬间瘫痪。当时还没配置自动故障转移,等到运维手动切换时已经流失了上百万订单——这惨痛教训让我彻底明白Always On的价值。

就像足球比赛的替补队员机制,Always On自动故障转移让数据库服务拥有随时待命的"替补选手"。当主库(Principal)出现故障时,秒级切换备用库(Secondary)接棒,整个过程无需人工干预。

二、手把手搭建高可用集群

(本章技术栈:Windows Server 2022 + SQL Server 2022 Enterprise)

  1. 先决条件检查清单
  • 三台域控环境服务器(主节点、辅助节点、见证服务器)
  • 共享存储或每节点独立存储
  • 相同版本的SQL Server实例
  • 开放5022端口用于端点通信
  1. 见证服务器配置示例
Install-WindowsFeature -Name Failover-Clustering -IncludeManagementTools

# 创建集群(注意替换实际IP)
New-Cluster -Name AGCluster -Node "NodeA","NodeB" -StaticAddress 192.168.1.100 -NoStorage
  1. 数据库镜像端点配置
-- 在所有节点执行
CREATE ENDPOINT AG_Endpoint
STATE = STARTED
AS TCP (LISTENER_PORT = 5022)
FOR DATABASE_MIRRORING (ROLE = ALL)

三、完整可用性组创建实录

  1. 创建可用性组
-- 主节点执行
CREATE AVAILABILITY GROUP Sales_AG
WITH (AUTOMATED_BACKUP_PREFERENCE = PRIMARY)
FOR DATABASE SalesDB
REPLICA ON
'NODEA\SQL2022' WITH (
    ENDPOINT_URL = 'TCP://nodeA:5022',
    AVAILABILITY_MODE = SYNCHRONOUS_COMMIT,
    FAILOVER_MODE = AUTOMATIC,
    SEEDING_MODE = AUTOMATIC
),
'NODEB\SQL2022' WITH (
    ENDPOINT_URL = 'TCP://nodeB:5022',
    AVAILABILITY_MODE = SYNCHRONOUS_COMMIT,
    FAILOVER_MODE = AUTOMATIC,
    SEEDING_MODE = AUTOMATIC
)
  1. 辅助节点接入
-- 在辅助节点执行
ALTER AVAILABILITY GROUP Sales_AG JOIN
ALTER AVAILABILITY GROUP Sales_AG GRANT CREATE ANY DATABASE

四、故障转移验证大全

  1. 模拟主库宕机
# 突然关闭主库服务
Stop-Service -Name MSSQLSERVER -Force

# 验证日志输出(关键指标)
Get-ClusterLog -Node NodeB -UseLocalTime | Select-String "failover"
  1. 应用重连测试代码(C#示例)
var connectionString = "Server=AGListener;Database=SalesDB;MultiSubnetFailover=True";
using (var conn = new SqlConnection(connectionString))
{
    try 
    {
        conn.Open();
        // 断线重试逻辑
        var retryPolicy = Policy
            .Handle<SqlException>()
            .WaitAndRetry(3, retryAttempt => 
                TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
            
        retryPolicy.Execute(() => 
        {
            using (var cmd = new SqlCommand("SELECT @@SERVERNAME", conn))
            {
                Console.WriteLine($"当前连接服务器: {cmd.ExecuteScalar()}");
            }
        });
    }
    catch (Exception ex)
    {
        Console.WriteLine($"连接异常: {ex.Message}");
    }
}

五、技术选择的利弊权衡

🟢 核心优势:

  • 秒级故障切换(实测平均1.8秒)
  • 支持最多8个同步副本
  • 允许读取扩展
  • 集成Windows故障转移集群

🔴 已知限制:

  • 需要企业版授权
  • 跨子网延迟可能触发误切换
  • 日志传输带宽消耗较高
  • 无法自动重建损坏副本

六、前辈的避坑指南

  1. 存储层级同步问题: 某次存储阵列延迟导致日志积压,同步延迟达到6小时。解决方案是:
-- 监控同步状态
SELECT 
    ag.name AS AG_Name,
    ar.replica_server_name,
    drs.database_name,
    drs.synchronization_state_desc,
    drs.log_send_queue_size
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
  1. 网络隔离假死现象: 建议设置更精准的检测阈值
(Get-Cluster).SameSubnetThreshold = 20
(Get-Cluster).CrossSubnetThreshold = 40

七、适用场景推荐

✅ 推荐使用场景:

  • 金融交易系统
  • 电商大促期间
  • 医疗HIS系统
  • 物联网实时数据处理

❌ 不推荐场景:

  • 开发测试环境
  • 低于50GB的小型数据库
  • 跨地域多活部署
  • 非Windows平台

八、行业最佳实践

某证券公司真实架构:

  • 主库:DL580 Gen10物理机
  • 辅助库:VMware虚拟化集群
  • 见证服务器:Azure云托管实例
  • 网络延迟:内网<2ms,异地灾备<50ms 实现了全年99.999%的可用性指标

九、结语

经历了那次生产事故后,我为所有核心系统都部署了Always On。最近三年处理了17次硬件故障、5次网络中断,但业务系统始终保持零感知。自动故障转移就像给数据库上了双保险,让它具备"断臂求生"的能力——这是DBA能给业务最坚实的承诺。