SQL Server Always On 可用性组在Linux上的部署指南(步骤/命令/脚本)

适用平台:RHEL 7/8/9、Ubuntu 18.04/20.04/22.04。SQL Server 2025 起不再支持 SLES。

集群管理器:Linux 上使用 Pacemaker + Corosync (不使用 WSFC);集群类型为 CLUSTER_TYPE = EXTERNAL。

高可用(可自动故障转移)在 Linux 上要求 3 个节点(2 个同步提交副本 + 1 个配置仅副本,或 3 个完整副本)。


一、与 Windows 方案的关键差异

对比项 Windows(WSFC) Linux(Pacemaker)
集群管理器 WSFC Pacemaker + Corosync
是否需要 AD 域 需要(或工作组集群) 通常不需要
启用 AG 方式 配置管理器 / PowerShell mssql-conf
端点认证 Windows 认证 证书认证(不支持 Windows 集成认证)
故障转移模式 AUTOMATIC / MANUAL FAILOVER_MODE = EXTERNAL(由 Pacemaker 编排)
侦听器 内置 VNN 无等价物,需手工在 DNS 注册 IP
集群类 DMV 正常返回 返回空行(DMV 为 WSFC 设计)
部署顺序 先建 WSFC 再装 SQL 可先装 SQL 再建 Pacemaker,或反之

二、环境准备

步骤 1:主机名与 /etc/hosts(所有节点)

bash 复制代码
# 每台节点分别设置主机名,并保证三节点互相解析
sudo hostnamectl set-hostname node1
# 所有节点统一写入 /etc/hosts
sudo tee -a /etc/hosts <<'EOF'
10.0.0.11  node1
10.0.0.12  node2
10.0.0.13  node3
EOF

# 校验
ping -c 2 node2
ping -c 2 node3

节点名必须与 SQL Server @@SERVERNAME 一致,否则集群认证会失败;无法一致时用 pcs cluster auth 的 addr 选项指定匹配地址。

步骤 2:安装 SQL Server 与高可用组件(所有节点)

bash 复制代码
# 安装 SQL Server(按官方源配置后)
sudo dnf install -y mssql-server
sudo /opt/mssql/bin/mssql-conf setup

# 安装高可用组件(RHEL 系)
sudo dnf install -y pacemaker pcs psmisc policycoreutils-python-utils

# 安装 SQL Server HA 资源代理与 Agent 包
sudo dnf install -y mssql-server-ha mssql-server-agent

# Ubuntu 系对应使用 apt install pacemaker pcs psmisc 及 mssql-server-ha

步骤 3:开放防火墙端口(所有节点)

bash 复制代码
# 1433 数据库端口;5022 镜像端点端口
sudo firewall-cmd --zone=public --add-port=1433/tcp --permanent
sudo firewall-cmd --zone=public --add-port=5022/tcp --permanent
sudo firewall-cmd --reload

# 验证
sudo firewall-cmd --zone=public --list-ports

三、启用 Always On 并配置证书端点

步骤 4:启用可用性组功能(所有节点)

bash 复制代码
sudo /opt/mssql/bin/mssql-conf set hadr.hadrenabled 1
sudo systemctl restart mssql-server
# 确认
sudo /opt/mssql/bin/mssql-conf get hadr.hadrenabled

步骤 5:创建主密钥、证书并导出(每个节点各做一次)

Linux 端点为证书认证,需在每个节点创建本机主密钥 + 本机证书 ,导出 .cer 后与其他节点交换。

以下脚本以 node1 为例,node2/node3 执行时替换证书名与文件名。

sql 复制代码
USE master;
GO
-- 1) 创建数据库主密钥
CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'Str0ngP@ssw0rd!Node1';
GO
-- 2) 创建本机服务器证书
CREATE CERTIFICATE node1_cert
    WITH SUBJECT = 'node1 AG Certificate', EXPIRY_DATE = '20301231';
GO
-- 3) 导出证书(不含私钥),供其他节点导入
BACKUP CERTIFICATE node1_cert
    TO FILE = '/var/opt/mssql/data/node1_cert.cer';
GO

将三个节点的 .cer 文件互相复制到各节点的 /var/opt/mssql/data/ 目录:

bash 复制代码
# 在 node1 上把其他节点证书拷入(示例用 scp,实际按环境方式传输)
scp node2:/var/opt/mssql/data/node2_cert.cer /var/opt/mssql/data/
scp node3:/var/opt/mssql/data/node3_cert.cer /var/opt/mssql/data/
sudo chown mssql:mssql /var/opt/mssql/data/*_cert.cer

步骤 6:创建数据库镜像端点并交换证书信任(每个节点)

sql 复制代码
USE master;
GO
-- 1) 导入其他节点的证书
CREATE CERTIFICATE node2_cert FROM FILE = '/var/opt/mssql/data/node2_cert.cer';
CREATE CERTIFICATE node3_cert FROM FILE = '/var/opt/mssql/data/node3_cert.cer';
GO
-- 2) 由对端证书创建登录并授予端点连接权限
CREATE LOGIN node2_login FROM CERTIFICATE node2_cert;
CREATE LOGIN node3_login FROM CERTIFICATE node3_cert;
GRANT CONNECT ON ENDPOINT::Hadr_endpoint TO node2_login;
GRANT CONNECT ON ENDPOINT::Hadr_endpoint TO node3_login;
GO
-- 3) 创建端点,认证方式为证书,包含全部三个节点证书
CREATE ENDPOINT [Hadr_endpoint]
    STATE = STARTED
    AS TCP (LISTENER_PORT = 5022, LISTENER_IP = ALL)
    FOR DATABASE_MIRRORING (
        ROLE = ALL,
        AUTHENTICATION = CERTIFICATE node1_cert, node2_cert, node3_cert,
        ENCRYPTION = REQUIRED ALGORITHM AES
    );
GO
-- 4) 确认端点端口
SELECT name, type_desc, port FROM sys.tcp_endpoints WHERE type_desc = 'DATABASE_MIRRORING';

每个节点只需一个镜像端点,所有 AG/镜像会话共用;端点已存在且在用时重用,不要删除重建。

步骤 7:准备数据库(主副本节点)

sql 复制代码
ALTER DATABASE [SalesDB] SET RECOVERY FULL;
GO
BACKUP DATABASE [SalesDB] TO DISK = N'/var/opt/mssql/backup/SalesDB_full.bak' WITH INIT, COMPRESSION;
BACKUP LOG [SalesDB] TO DISK = N'/var/opt/mssql/backup/SalesDB_log.trn' WITH INIT, COMPRESSION;
GO

步骤 8:创建可用性组(主副本节点执行,CLUSTER_TYPE = EXTERNAL)

sql 复制代码
CREATE AVAILABILITY GROUP [ag1]
WITH (
    CLUSTER_TYPE = EXTERNAL,
    AUTOMATED_BACKUP_PREFERENCE = SECONDARY,
    DB_FAILOVER = ON
)
FOR DATABASE [SalesDB]
REPLICA ON
    N'node1' WITH (
        ENDPOINT_URL = N'TCP://node1:5022',
        AVAILABILITY_MODE = SYNCHRONOUS_COMMIT,
        FAILOVER_MODE = EXTERNAL,
        SEEDING_MODE = AUTOMATIC,
        SECONDARY_ROLE (ALLOW_CONNECTIONS = READ_ONLY)
    ),
    N'node2' WITH (
        ENDPOINT_URL = N'TCP://node2:5022',
        AVAILABILITY_MODE = SYNCHRONOUS_COMMIT,
        FAILOVER_MODE = EXTERNAL,
        SEEDING_MODE = AUTOMATIC,
        SECONDARY_ROLE (ALLOW_CONNECTIONS = READ_ONLY)
    ),
    N'node3' WITH (
        ENDPOINT_URL = N'TCP://node3:5022',
        AVAILABILITY_MODE = CONFIGURATION_ONLY,   -- 配置仅副本,参与仲裁不存数据
        FAILOVER_MODE = EXTERNAL,
        SEEDING_MODE = AUTOMATIC
    );
GO

辅助节点加入并授权(node2、node3 各执行)

sql 复制代码
ALTER AVAILABILITY GROUP [ag1] JOIN;
GO
ALTER AVAILABILITY GROUP [ag1] GRANT CREATE ANY DATABASE;
GO

说明:CLUSTER_TYPE 在创建后不可通过 ALTER 修改 ;若误建为 External/NONE 需删除重建。AVAILABILITY_MODE 可用 SYNCHRONOUS_COMMIT / ASYNCHRONOUS_COMMIT,自动故障转移目标必须是同步提交。

步骤 9:为 Pacemaker 创建 SQL 登录并授权(主副本节点)

sql 复制代码
CREATE LOGIN [PMLogin] WITH PASSWORD = N'P@ceMaker#2026';
GO
GRANT VIEW SERVER STATE TO [PMLogin];
GO
GRANT ALTER, CONTROL, VIEW DEFINITION ON AVAILABILITY GROUP::[ag1] TO [PMLogin];
GO

最小权限方案:授予 VIEW SERVER STATE 及 AG 上的 ALTER / CONTROL / VIEW DEFINITION 即可,避免给 sysadmin。


四、构建 Pacemaker 集群

步骤 10:初始化并创建集群(在任一节点执行)

bash 复制代码
# 1) 设置 hacluster 用户密码(所有节点必须相同)
sudo passwd hacluster

# 2) 启动 pcsd 并设置开机自启(所有节点)
sudo systemctl enable --now pcsd

# 3) 节点认证(RHEL 7 写法)
sudo pcs cluster auth node1 node2 node3 -u hacluster -p 'YourHaclusterPwd' --force

# 4) 创建集群(RHEL 7 写法)
sudo pcs cluster setup --name agcluster node1 node2 node3 --force

# 5) 启动并开机自启(所有节点)
sudo pcs cluster start --all
sudo pcs cluster enable --all

# 6) 查看状态
sudo pcs status

RHEL 8+/9 及 Ubuntu 使用新版写法:

bash 复制代码
sudo pcs host auth node1 node2 node3 -u hacluster -p 'YourHaclusterPwd'
sudo pcs cluster setup agcluster node1 node2 node3 --force
sudo pcs cluster start --all
sudo pcs cluster enable --all
sudo pcs status

集群所有节点必须使用同一 Linux 发行版,不可混用 RHEL 与 SLES 节点。

步骤 11:创建 AG 资源与虚拟 IP 资源(在任一节点执行)

bash 复制代码
# 1) 创建可用性组资源
#    RHEL 7(HA agent v1,master 角色)
sudo pcs resource create ag_cluster ocf:mssql:ag ag_name=ag1 meta failure-timeout=60s master notify=true

#    RHEL 8+ / Ubuntu(HA agent v1,promotable 角色)
sudo pcs resource create ag_cluster ocf:mssql:ag ag_name=ag1 meta failure-timeout=60s promotable notify=true

#    HA agent v2(资源代理为 ocf:mssql:agv2,其余参数一致)
# sudo pcs resource create ag_cluster ocf:mssql:agv2 ag_name=ag1 meta failure-timeout=30s promotable notify=true

# 2) 创建虚拟 IP 资源(替换为可用静态 IP)
sudo pcs resource create virtualip ocf:heartbeat:IPaddr2 ip=10.0.0.100

# 3) 共置约束:VIP 与 AG 提升副本同节点
sudo pcs constraint colocation add virtualip with ag_cluster-clone INFINITY

# 4) 顺序约束:先提升 AG,再启动 VIP(避免 IP 先漂移指向旧辅助副本)
sudo pcs constraint order promote ag_cluster-clone then start virtualip

# 5) 查看资源与约束
sudo pcs status
sudo pcs constraint show

RHEL 8.x / Ubuntu 18.04 起资源名可能表现为 ag_cluster-clone(promotable clone)。

未添加显式顺序约束时,colocation 的隐式顺序会让虚拟 IP 在 AG 提升前先启动,导致 IP 临时指向故障转移前的辅助副本。


五、验证与故障转移

步骤 12:验证(SQL 侧 + 集群侧)

sql 复制代码
-- 副本角色与同步健康
SELECT ag.name AS ag_name, ar.replica_server_name, ars.role_desc,
       ars.operational_state_desc, ars.synchronization_health_desc
FROM sys.availability_groups ag
JOIN sys.availability_replicas ar ON ag.group_id = ar.group_id
JOIN sys.dm_hadr_availability_replica_states ars ON ar.replica_id = ars.replica_id;

-- 数据库同步状态与发送/重做队列
SELECT DB_NAME(drs.database_id) AS db_name, ar.replica_server_name,
       drs.synchronization_state_desc, drs.synchronization_health_desc,
       drs.log_send_queue_size, drs.redo_queue_size
FROM sys.dm_hadr_database_replica_states drs
JOIN sys.availability_replicas ar ON drs.replica_id = ar.replica_id;
bash 复制代码
# 集群状态:资源应显示 ag_cluster 为 Promoted,virtualip 在 Master 节点
sudo pcs status
sudo pcs resource status

Linux 上查询集群信息的 AG DMV 返回空行属正常(DMV 面向 WSFC 设计),集群状态以 pcs status 为准。

步骤 13:故障转移测试

bash 复制代码
# 方式一:手工把 AG 资源迁移到另一节点(推荐验证)
sudo pcs resource move ag_cluster-clone node2
# 等待提升完成后清理临时约束
sudo pcs resource clear ag_cluster-clone

# 方式二:停掉当前主节点 SQL Server 模拟故障
sudo systemctl stop mssql-server
# 观察 Pacemaker 是否自动提升其他节点
sudo pcs status

步骤 14:客户端连接(侦听器 / DNS)

Linux 无内置侦听器 VNN,需手工在 DNS 为侦听器名称注册 IP(即虚拟 IP):

bash 复制代码
# 示例:在 DNS 中为 ag1-listener 注册 10.0.0.100
# 客户端连接字符串使用 TCP,多子网场景建议加 MultiSubnetFailover=True

六、常见误区与注意事项

  1. 版本边界:完整 AG 仅 Enterprise 支持;Standard 仅支持基本可用性组(2 副本、单库、辅助副本不可读/不可备份)。
  2. 认证方式:Linux 端点必须用证书认证,不支持 Windows 集成认证;证书需在各节点互相导入。
  3. 节点数:Linux 高可用要求 3 节点(2 同步 + 1 配置仅副本或 3 完整副本);两节点无法满足自动故障转移的仲裁要求。
  4. 集群类型不可改 :CLUSTER_TYPE 创建后不能 ALTER 修改;CLUSTER_TYPE = NONE 的 AG 不需要也不能由 Pacemaker 管理。
  5. 发行版一致:Pacemaker 集群所有节点必须同一发行版,禁止混用 RHEL/SLES。
  6. RHEL 9 + SELinux:SQL Server 2022 CU16 及更早以 SELinux confined 运行时可能导致 Pacemaker 集群异常,需以 unconfined 安装或升级到 CU17。
  7. 辅助副本路径 :主副本新增数据文件时,若辅助副本对应目录不存在,辅助库会进入 NOT SYNCHRONIZING;多副本应统一目录结构。
  8. 自动种子压缩:可启用跟踪标志 9567 在自动种子设定过程中压缩数据流。
  9. SLES 支持:SQL Server 2025 起不再支持 SUSE Linux Enterprise Server。

七、快速命令速查

目的 命令
启用 AG sudo /opt/mssql/bin/mssql-conf set hadr.hadrenabled 1 && sudo systemctl restart mssql-server
认证集群节点 sudo pcs cluster auth node1 node2 node3 -u hacluster -p ***
创建集群 sudo pcs cluster setup --name agcluster node1 node2 node3 --force
启动集群 sudo pcs cluster start --all
创建 AG 资源 sudo pcs resource create ag_cluster ocf:mssql:ag ag_name=ag1 meta failure-timeout=60s promotable notify=true
创建 VIP sudo pcs resource create virtualip ocf:heartbeat:IPaddr2 ip=10.0.0.100
查看状态 sudo pcs status
手工迁移 sudo pcs resource move ag_cluster-clone node2