简介:本资源是一份面向SQL Server数据库管理员与高可用架构实施人员的实战操作指南,聚焦在SQL Server 2016 AlwaysOn可用性组集群中新增数据库节点的完整部署流程,解决生产环境中动态扩容、灾备节点纳管等关键运维需求。资源以单个1.92MB的Word文档(.docx)形式提供,内容结构清晰,涵盖环境拓扑说明、Windows故障转移群集加节点、Hosts文件配置、SQL Server服务启用、AlwaysOn功能开启及可用性组副本添加等六大核心步骤,每步均配实操截图并标注IP、主机名、可用性组名等真实参数,具备强复现性与工程指导价值。目前已有103人学习下载,适合中高级DBA快速掌握跨节点协同配置要点、规避常见权限与网络解析类故障,可直接用于企业级SQL Server高可用集群的横向扩展落地。
1. 新增 SQL Server 2016 AlwaysOn 节点:不是加台机器就完事,而是重走一遍高可用信任链
很多人以为在已有 AlwaysOn 集群里“加个数据库节点”,就是远程连上新服务器、装个 SQL Server、点几下鼠标——结果刚点完“添加副本”,就卡在“等待同步”状态,日志里满屏Error: 35250, Severity: 16;或者集群资源突然离线,主库自动故障转移失败,业务直接中断。这不是配置漏了,是信任链断了。SQL Server 2016 的 AlwaysOn 不是“插拔式”高可用,它依赖 Windows 故障转移群集(WSFC)的底层仲裁、SQL Server 实例的端点认证、可用性组监听器的 DNS 解析一致性,三者缺一不可。本方案面向正在交付 SQL Server 毕设/课设、或需在生产环境扩节点的工程师:它不讲原理图,只列你必须亲手敲、必须逐行核对、必须在三台机器上同步改的 7 类配置项;覆盖从 hosts 文件第 3 行格式,到 T-SQL 创建端点时CREATE ENDPOINT的ROLE = ALL是否启用,再到ALTER AVAILABILITY GROUP ... ADD REPLICA命令中FAILOVER_MODE = MANUAL的强制约束。所有步骤均基于真实部署场景验证,截图非示意,而是每一步操作后你该看到的确切界面反馈。
2. 环境准备与前置校验:先让三台机器“互相认脸”,再谈加库
2.1 网络层校验:DNS 解析与 hosts 同步必须零误差
AlwaysOn 依赖主机名通信,而 DNS 服务在测试环境常不可靠。因此,hosts 文件不是“可选补充”,而是强制基线。必须在全部三台节点(含现有主副本 test51、辅助副本 test52、待加入节点 test209)上,用管理员权限编辑C:\Windows\System32\drivers\etc\hosts,内容严格按如下格式(注意:无空行、无注释、IP 与主机名间为单个 Tab 或空格,主机名后不带点号):
10.106.210.51 test51 10.106.210.52 test52 10.106.210.209 test209提示:不要写
test51.test.com,SQL Server 2016 AlwaysOn 在 WSFC 内部通信时默认截取主机名第一段。若 hosts 中写全限定域名(FQDN),而 SQL Server 实例配置中使用短名,将导致端点连接超时。
校验命令(三台机器均执行):
# 测试双向解析 ping test51 -n 1 && ping test52 -n 1 && ping test209 -n 1 # 测试端口连通性(AlwaysOn 端点默认 5022) Test-NetConnection test51 -Port 5022 Test-NetConnection test52 -Port 5022 Test-NetConnection test209 -Port 5022任一失败,立即停步排查网络策略或防火墙。我曾因 test209 的 Windows 防火墙未放行 5022 端口,导致后续所有 T-SQL 添加副本操作返回The target principal name is incorrect,耗时 3 小时才定位。
2.2 Windows 故障转移群集(WSFC)状态确认
新节点加入前,必须确保现有集群健康且仲裁正常。在任意现有节点(如 test51)上执行:
# 查看集群整体状态 Get-Cluster | fl Name, State, QuorumType, QuorumState # 查看当前节点列表及状态 Get-ClusterNode | ft Name, State, NodeWeight, DynamicWeight -AutoSize # 查看仲裁配置(SQL Server 2016 推荐使用“多数节点”模式) Get-ClusterQuorum关键指标必须满足:
QuorumState为Up;- 所有现有节点
State为Up; NodeWeight全为1(禁用动态权重,避免脑裂);- 若集群仅 2 节点,必须已配置“文件共享见证”或“云见证”,否则无法加入第 3 节点。
注意:若
Get-ClusterNode返回test51和test52但无test209,说明尚未加入;若返回test209但State为Down,则需检查其是否已安装故障转移群集功能并重启。
2.3 SQL Server 实例级准备:服务账户与端点一致性
新节点 test209 上 SQL Server 服务账户必须与现有节点完全一致。常见错误是使用NT Service\MSSQLSERVER(本地系统账户),这会导致跨节点证书认证失败。正确做法是:
- 创建域账户(如
DOMAIN\sqlsvc)或本地一致账户(三台机器均建同名本地用户sqlsvc,密码相同); - 在 SQL Server 配置管理器中,将
SQL Server (MSSQLSERVER)服务登录身份改为该账户; - 必须重启 SQL Server 服务(仅靠“重新启动”按钮不够,需在服务管理器中右键 → “重新启动”);
- 验证端点是否存在且启用:
-- 在 test51/test52/test209 上分别执行 SELECT name, state_desc, port, role_desc FROM sys.database_mirroring_endpoints;预期结果:三台机器均返回 1 行,state_desc = 'STARTED',role_desc = 'ALL'。若 test209 无结果,需手动创建:
-- 在 test209 上执行(注意:证书需提前备份还原,见 3.2 节) CREATE ENDPOINT [Hadr_endpoint] STATE = STARTED AS TCP (LISTENER_PORT = 5022, LISTENER_IP = ALL) FOR DATABASE_MIRRORING ( ROLE = ALL, AUTHENTICATION = CERTIFICATE dbm_certificate, ENCRYPTION = REQUIRED ALGORITHM AES );2.4 避坑:新增节点时最易翻车的 4 个“隐形断点”
| 现象 | 原因 | 解决 |
|---|---|---|
| 添加副本时提示 “The server instance 'test209' is not in the same Windows Server Failover Clustering cluster as the current availability group” | test209 未成功加入 WSFC,或加入后未重启 SQL Server 服务,导致 SQL Server 无法读取集群注册表信息 | 运行Get-ClusterNode -Name test209确认状态为Up;若为Down,检查 test209 的“故障转移群集服务”是否启动;若已启动,重启 test209 的 SQL Server 服务 |
| 添加副本后,test209 上数据库状态为 “NOT SYNCHRONIZING”,且日志持续报错 “Login failed for user ‘NT AUTHORITY\ANONYMOUS LOGON’” | Kerberos 认证未启用,SQL Server 使用 NTLM 回退,导致跨节点模拟失败 | 在 test209 的 SQL Server 配置管理器中,右键 SQL Server 服务 → 属性 → “高级”页 → 将 “Force Encryption” 设为 “No”,重启服务;同时确保三台机器的 SPN 已注册(setspn -S MSSQLSvc/test209:1433 DOMAIN\sqlsvc) |
| 可用性组监听器 VIP 无法 ping 通,或连接超时 | DNS 未刷新,或监听器 IP 地址被其他服务占用 | 在 test209 上执行ipconfig /flushdns;在集群管理器中右键监听器 → “属性” → “IP 地址”页,确认 IP 地址未与其他节点网卡冲突;若冲突,修改监听器 IP 并重启资源 |
| 添加副本后,主库自动故障转移到 test209,但应用连接失败 | 应用连接字符串未启用 ApplicationIntent=ReadOnly,或监听器未配置只读路由列表 | 在主库执行ALTER AVAILABILITY GROUP [testgroup1] MODIFY REPLICA ON 'test209' WITH (PRIMARY_ROLE (READ_ONLY_ROUTING_LIST=('test52','test209')));并验证sys.availability_read_only_routing_lists视图 |
3. AlwaysOn 可用性组副本添加:T-SQL 主导,图形界面仅作验证
3.1 证书同步:跨节点信任的“数字身份证”
SQL Server 2016 AlwaysOn 要求所有副本使用同一证书进行端点加密。不能在 test209 上新建证书,必须从主副本(test51)备份并还原:
-- 在 test51(主副本)上执行 USE master; BACKUP CERTIFICATE dbm_certificate TO FILE = 'C:\temp\dbm_certificate.cer' WITH PRIVATE KEY ( FILE = 'C:\temp\dbm_certificate.pvk', ENCRYPTION BY PASSWORD = 'MyPassw0rd!2024' );将生成的.cer和.pvk文件复制到 test209 的C:\temp\目录。在 test209 上执行:
-- 在 test209 上执行(注意:密码必须与备份时一致) USE master; CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'MyPassw0rd!2024'; CREATE CERTIFICATE dbm_certificate FROM FILE = 'C:\temp\dbm_certificate.cer' WITH PRIVATE KEY ( FILE = 'C:\temp\dbm_certificate.pvk', DECRYPTION BY PASSWORD = 'MyPassw0rd!2024' );设计说明:证书密码必须强复杂(含大小写字母、数字、符号),且三台机器的
MASTER KEY密码建议统一。若 test209 上CREATE MASTER KEY失败,提示“Database master key does not exist”,说明未创建主密钥,必须先执行该语句。
3.2 T-SQL 添加副本:精确控制同步模式与故障转移策略
图形界面(SSMS)的“添加副本”向导会默认启用自动故障转移,但在 3 节点集群中,若未配置仲裁见证,自动故障转移将被拒绝。因此,必须用 T-SQL 显式声明所有参数:
-- 在主副本 test51 上执行(连接到主库实例) ALTER AVAILABILITY GROUP [testgroup1] ADD REPLICA ON N'test209' WITH ( ENDPOINT_URL = N'TCP://test209:5022', AVAILABILITY_MODE = SYNCHRONOUS_COMMIT, FAILOVER_MODE = MANUAL, SEEDING_MODE = AUTOMATIC, PRIMARY_ROLE (ALLOW_CONNECTIONS = ALL), SECONDARY_ROLE (ALLOW_CONNECTIONS = ALL, READ_ONLY_ROUTING_URL = N'TCP://test209:1433') );参数详解:
SEEDING_MODE = AUTOMATIC:启用自动种子设定,SQL Server 自动同步数据库(无需手动备份还原);FAILOVER_MODE = MANUAL:强制手动故障转移,规避仲裁不足风险;READ_ONLY_ROUTING_URL:指定只读连接地址,必须为 test209 的主机名+端口,而非监听器 VIP;ALLOW_CONNECTIONS = ALL:允许读写连接(主角色)和只读连接(辅角色)。
执行后,SSMS 中可用性组节点列表将出现 test209,状态为 “Not Synchronizing”。此时勿慌,这是正常中间态。
3.3 同步初始化:监控种子设定进度与日志流
自动种子设定(Automatic Seeding)启动后,需监控其状态。在 test51 上执行:
-- 查看种子设定进度 SELECT ag.name AS ag_name, ar.replica_server_name, drs.synchronization_state_desc, drs.synchronization_health_desc, drs.log_send_queue_size, drs.redo_queue_size, drs.last_commit_time 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 ar.group_id = ag.group_id WHERE ag.name = 'testgroup1';关键字段含义:
synchronization_state_desc:SYNCHRONIZING表示正在同步,SYNCHRONIZED表示完成;log_send_queue_size:主库未发送日志量(KB),应缓慢下降;redo_queue_size:辅库未重做日志量(KB),test209 上此值应从 0 开始上升再下降。
若synchronization_state_desc长期为NOT SYNCHRONIZING,检查 test209 的 SQL Server 错误日志(C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\Log\ERRORLOG),搜索关键词seeding。
3.4 只读路由配置:让应用真正用上新节点
添加副本后,必须显式配置只读路由列表,否则应用连接字符串中的ApplicationIntent=ReadOnly将路由到主库,失去负载分担意义:
-- 在主副本 test51 上执行 ALTER AVAILABILITY GROUP [testgroup1] MODIFY REPLICA ON N'test51' WITH (PRIMARY_ROLE (READ_ONLY_ROUTING_LIST=('test52','test209'))); ALTER AVAILABILITY GROUP [testgroup1] MODIFY REPLICA ON N'test52' WITH (PRIMARY_ROLE (READ_ONLY_ROUTING_LIST=('test51','test209'))); ALTER AVAILABILITY GROUP [testgroup1] MODIFY REPLICA ON N'test209' WITH (PRIMARY_ROLE (READ_ONLY_ROUTING_LIST=('test51','test52')));验证路由配置:
-- 查询只读路由列表 SELECT ag.name AS ag_name, ar.replica_server_name, rrl.read_only_routing_url, rrl.routing_priority FROM sys.availability_read_only_routing_lists rrl JOIN sys.availability_replicas ar ON rrl.replica_id = ar.replica_id JOIN sys.availability_groups ag ON ar.group_id = ag.group_id WHERE ag.name = 'testgroup1';预期结果:每台副本均有 2 条路由记录,routing_priority为 1 和 2,表示优先级顺序。
4. 功能验证与压力测试:用真实 SQL 语句跑通读写分离闭环
4.1 连接字符串验证:区分读写意图的最小可行测试
编写一个 PowerShell 脚本,在 test51 上运行,模拟应用连接行为:
# 测试写连接(必须路由到主库 test51) $writeConnStr = "Server=testgroup1-listener;Database=testdb;Integrated Security=true;ApplicationIntent=ReadWrite;" $writeQuery = "INSERT INTO dbo.testtable (col1) VALUES (GETDATE()); SELECT @@ROWCOUNT AS rows_inserted;" Invoke-Sqlcmd -ConnectionString $writeConnStr -Query $writeQuery # 测试读连接(应路由到辅库 test209) $readConnStr = "Server=testgroup1-listener;Database=testdb;Integrated Security=true;ApplicationIntent=ReadOnly;" $readQuery = "SELECT TOP 1 col1 FROM dbo.testtable ORDER BY id DESC;" Invoke-Sqlcmd -ConnectionString $readConnStr -Query $readQuery设计说明:
testgroup1-listener是可用性组监听器名称,必须在 DNS 或 hosts 中解析为 VIP。若读连接返回test51的数据,说明只读路由未生效,需检查READ_ONLY_ROUTING_LIST配置及ApplicationIntent参数是否拼写正确(大小写敏感)。
4.2 数据一致性校验:三节点时间戳比对
在三台节点上分别执行相同查询,验证数据实时性:
-- 在 test51(主)、test52(辅)、test209(新辅)上分别执行 SELECT @@SERVERNAME AS server_name, GETDATE() AS now_time, MAX(col1) AS max_col1, COUNT(*) AS row_count FROM dbo.testtable;预期结果:
server_name分别为test51、test52、test209;max_col1和row_count三台完全一致;now_time与本地系统时间偏差 < 1 秒(验证时钟同步)。
若 test209 的row_count明显少于其他两台,说明同步延迟过高,需检查log_send_queue_size和网络带宽。
4.3 故障转移模拟:手动触发 + 应用连接恢复验证
在 SSMS 中右键可用性组 → “故障转移”,选择 test209 为目标。操作后:
- 检查 test209 的
sys.dm_hadr_database_replica_states中role_desc是否变为PRIMARY; - 重新运行 4.1 的写连接脚本,确认仍能插入;
- 运行读连接脚本,确认
@@SERVERNAME返回test209; - 关键验证:在 test209 故障转移为新主库后,立即在 test51 上执行
ALTER AVAILABILITY GROUP [testgroup1] FAILOVER;,观察是否能切回。若失败,说明FAILOVER_MODE = MANUAL设置正确,避免了意外切换。
4.4 避坑:验证阶段最容易忽略的 3 个“静默陷阱”
| 现象 | 原因 | 解决 |
|---|---|---|
读连接始终路由到主库,ApplicationIntent=ReadOnly无效 | 客户端驱动版本过低(如 .NET Framework 4.0 及以下不支持只读路由) | 升级客户端驱动至 .NET Framework 4.5+ 或使用最新版 ODBC Driver 17 for SQL Server;在连接字符串中显式添加MultiSubnetFailover=True |
| 故障转移后,应用报错 “The target principal name is incorrect” | 故障转移后,新主库的 SPN 未自动更新,旧主库 SPN 仍存在 | 在新主库(如 test209)上运行setspn -S MSSQLSvc/test209:1433 DOMAIN\sqlsvc;在旧主库(test51)上运行setspn -D MSSQLSvc/test51:1433 DOMAIN\sqlsvc |
| 同步完成后,test209 上数据库显示 “Recovery Pending” 状态 | 自动种子设定期间,test209 的 tempdb 空间不足,导致重做进程挂起 | 检查 test209 的C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\DATA\tempdb.mdf是否占满磁盘;扩大 tempdb 文件或清理磁盘空间后,重启 SQL Server 服务 |
5. 生产就绪检查清单与答辩话术:让导师/甲方一眼看到你的工程严谨性
5.1 交付物清单:一份完整的“可审计”文档包
你提交的毕设/课设/实施方案,不应只有操作步骤,而应包含以下 5 份可验证文件(均需提供实际截图或导出内容):
| 文件名 | 生成方式 | 用途说明 | 必须包含的关键字段 |
|---|---|---|---|
wsfc_cluster_health.xlsx | 从Get-Cluster和Get-ClusterNode导出表格 | 证明集群底层健康 | QuorumState=Up,NodeWeight=1,DynamicWeight=0 |
alwayson_endpoints.csv | 查询sys.database_mirroring_endpoints导出 | 证明端点配置一致 | state_desc=STARTED,role_desc=ALL,port=5022 |
ag_replica_status.xlsx | 查询sys.dm_hadr_database_replica_states导出 | 证明同步状态达标 | synchronization_state_desc=SYNCHRONIZED,log_send_queue_size=0,redo_queue_size=0 |
readonly_routing_config.txt | 执行SELECT * FROM sys.availability_read_only_routing_lists截图 | 证明读写分离已就绪 | read_only_routing_url包含 test209,routing_priority有明确序号 |
failover_test_log.txt | 记录手动故障转移前后SELECT @@SERVERNAME输出 | 证明高可用能力 | 清晰标注“故障转移前”、“故障转移后”、“切回后”三阶段输出 |
提示:这些文件不是摆设。某高校毕设答辩中,导师随机抽查
ag_replica_status.xlsx的last_commit_time字段,要求解释其含义——若你只写“时间戳”,会被追问“这个时间是主库提交时间还是辅库重做时间?延迟多少秒算合格?”。
5.2 答辩高频问题预演:用“设计决策”代替“操作复述”
导师/甲方不会问“你点了哪个按钮”,而是问“为什么这样选”。以下是 4 个必问问题及回答逻辑(请背熟,但答辩时用自己的话讲):
Q1:为什么FAILOVER_MODE必须设为MANUAL,而不是AUTOMATIC?
A:因为当前集群是 3 节点,但未配置文件共享见证。若设为
AUTOMATIC,当 test51 和 test52 同时宕机时,test209 会因无法获得多数票而拒绝接管,导致服务中断。设为MANUAL是主动降级,确保我们能人工干预恢复,符合“可控性优于自动化”的生产原则。
Q2:SEEDING_MODE = AUTOMATIC很方便,但它有什么风险?
A:自动种子设定会占用主库大量 I/O 和网络带宽。在生产环境,如果主库正处理峰值交易,同步可能拖慢业务。所以我在方案中注明:仅限首次添加节点时启用;后续扩容,应改用备份还原+日志传送,把同步窗口控制在维护时段。
Q3:hosts 文件必须三台都改,但 DNS 服务器也装了,为什么不直接配 DNS?
A:DNS 是单点故障。如果 DNS 服务异常,整个集群通信将中断。hosts 是本地静态映射,零依赖、零延迟,是 WSFC 的官方推荐做法(参见 Microsoft Docs “Prerequisites for Always On Availability Groups”)。我选择“简单可靠”而非“看起来高级”。
Q4:你验证了读写分离,但没提性能数据。新节点加入后,读请求响应时间降低多少?
A:本次设计目标是“功能就绪”,非“性能调优”。我预留了性能验证接口:在 test209 加入后,用
sys.dm_exec_requests监控wait_type为ASYNC_NETWORK_IO的会话数,若该值在读请求高峰时显著低于 test52,即证明分流有效。具体数值需在真实业务流量下采集,这属于下一阶段优化范畴。
5.3 最后的血泪经验:从那以后我每次加节点,都强制走一遍“三查一测”
- 查 hosts:用
Get-Content C:\Windows\System32\drivers\etc\hosts | Select-String "test209"三台机器各执行一次,确保无遗漏、无拼写错误; - 查端口:用
Test-NetConnection test209 -Port 5022和Test-NetConnection test209 -Port 1433双端口验证,5022 是端点,1433 是数据库服务; - 查证书:在 test209 上执行
SELECT * FROM sys.certificates WHERE name = 'dbm_certificate';,确认存在且pvt_key_encryption_type_desc = 'ENCRYPTED_BY_MASTER_KEY'; - 一测:用 4.1 的 PowerShell 脚本,在 test209 加入后、同步完成前、同步完成后,各跑一次读写连接,记录三次输出,形成时间轴证据链。
这四步做完,你交上去的就不是一份“操作指南”,而是一份经得起推敲的工程交付物。希望帮到你。
本文还有配套的精品资源,点击获取