备份维护计划突然失效?一个 SQL Server 主机名引发的大坑
在配置 SQL Server AlwaysOn 高可用性组的维护计划时,我们通常会使用如下 T-SQL 逻辑判断当前实例是否是“首选备份副本”:
1 | IF (SELECT master.sys.fn_hadr_backup_is_preferred_replica('MyDbName')) = 1 |
理论上,如果当前节点是备份首选副本(Preferred Replica),该函数会返回 1
,否则返回 0
。但我在某项目中遇到一个非常诡异的现象:始终返回 0,即使当前节点确实是主副本,导致维护计划中的备份逻辑无法触发。
问题分析
在排查过程中,我尝试以下方法:
- 用
QUOTENAME()
包裹数据库名,例如:SELECT fn_hadr_backup_is_preferred_replica('[MyDbName]')
,结果返回 1; - 用普通字符串
SELECT fn_hadr_backup_is_preferred_replica('MyDbName')
,始终返回 0; - 数据库确实位于主副本,AG 配置无误。
最终,我通过查询 @@SERVERNAME
发现,SQL Server 内部注册的服务器名与实际主机名不一致!
这是关键所在。
原因根源:SQL Server 安装时记录的本地服务器名未更新
SQL Server 在安装时会把当时的主机名注册进系统目录 sys.servers
中,并在内部函数中用于判断“本地实例”是否等于主副本。
但如果你之后更改了主机名,比如从 OLD-SERVER
改为 NEW-SERVER
,系统主机名虽然变了,但 SQL Server 并不会自动更新它的注册信息。
你可以用以下 SQL 验证这个不一致:
1 | SELECT |
解决方法:重新注册本地服务器名
只需执行以下三步:
第一步:删除旧的注册名
1 | EXEC sp_dropserver '旧服务器名'; |
其中 '旧服务器名'
替换为你当前 @@SERVERNAME
的返回值。
第二步:添加新的服务器名
如果你是默认实例:
1 | EXEC sp_addserver '新主机名', 'local'; |
如果你是命名实例(如 NEW-SERVER\SQL2022
):
1 | EXEC sp_addserver '新主机名\实例名', 'local'; |
可通过如下方式获取当前信息:
1 | SELECT |
第三步:重启 SQL Server 服务
只有重启 SQL Server 实例后,这些更改才会生效。可以通过服务管理器或以下 PowerShell 命令执行:
1 | Restart-Service -Name 'MSSQLSERVER' # 默认实例 |
验证结果
重新启动后,再次执行:
1 | SELECT @@SERVERNAME; |
应该可以看到 @@SERVERNAME
与主机名一致,同时 fn_hadr_backup_is_preferred_replica()
正确返回 1。
总结
✅ 如果你在使用
fn_hadr_backup_is_preferred_replica
时发现它始终返回 0,而当前实例确实是主副本,很可能是由于主机名变更后没有同步 SQL Server 内部注册信息。
通过执行 sp_dropserver
+ sp_addserver
+ 重启 SQL Server,就可以修复这个问题,确保 AlwaysOn 的备份判断逻辑恢复正常。