第九期:高可用与灾难恢复 —— 日志传送、复制、Always On
1. 高可用 vs 灾难恢复:两个不同的目标
| 维度 | 高可用(HA) | 灾难恢复(DR) |
|——|————-|—————|
| 目标 | 应对局部故障(服务器、磁盘、网络) | 应对大规模灾难(机房、城市、自然灾害) |
| 指标 | RTO:分钟级,RPO:秒级或零 | RTO:小时级,RPO:分钟到小时级 |
| 距离 | 同机房或同城 | 异地或跨区域 |
| 典型技术 | 故障转移集群,Always On | 日志传送,异地备份 |
| 自动切换 | 通常自动 | 通常手动 |
关键术语:
-
RTO(恢复时间目标):从故障到恢复服务的时间
-
RPO(恢复点目标):允许丢失的数据时间窗口
2. SQL Server 高可用技术全景
| 技术 | 范围 | 数据丢失 | 自动切换 | 复杂度 | 适用场景 |
|——|——|———-|———-|——–|———-|
| 故障转移集群 | 实例级 | 可能(取决于磁盘) | 是 | 中 | 共享存储,传统HA |
| 日志传送 | 数据库级 | 分钟级 | 否 | 低 | DR,报表服务器 |
| 事务复制 | 表级 | 秒级 | 否 | 高 | 数据分发,多主 |
| 合并复制 | 表级 | 分钟级 | 否 | 高 | 移动/离线场景 |
| 镜像(已弃用) | 数据库级 | 秒~零 | 是 | 中 | 老环境 |
| Always On AG | 数据库级 | 零(同步)| 是 | 中高 | 现代HA+DR首选 |
| Always On FCI | 实例级 | 可能 | 是 | 中 | 共享存储或无存储AG |
3. 故障转移集群(FCI)
架构图:
  客户端
  ↓
  虚拟网络名
  ↓
  活动节点 ← 心跳 ← 备用节点
  ↓ ↓
  共享存储(SAN)────┘
工作原理:
-
多台服务器共享同一存储(SAN、SMB文件共享)
-
SQL Server 服务只能在一个节点上运行
-
节点间通过心跳网络相互监控
-
故障时,备用节点挂载存储,启动服务
切换类型:
| 切换类型 | 触发条件 | 影响 |
|———-|———-|——|
| 计划内切换 | 手动,运维操作 | 短暂中断(秒级) |
| 故障自动切换 | 节点崩溃、网络中断 | 可能丢失未提交事务 |
| 强制仲裁切换 | 多数节点故障 | 可能丢失数据 |
优劣:
-
✅ RTO短(10-30秒),配置相对简单
-
❌ 共享存储是单点故障,成本高(SAN设备)
4. 日志传送(Log Shipping)
架构流程:
主服务器 辅助服务器
  ↓ ↓
事务日志备份 -----→ 复制日志文件 -----→ 还原(只读模式)
  ↓ ↓
日志备份文件夹 等待下一个日志
三个作业:
-
备份作业:在主服务器上定期备份事务日志
-
复制作业:将备份文件复制到辅助服务器
-
还原作业:在辅助服务器上还原日志(可以配置为待机/只读模式)
配置示例:
-- 主服务器设置
EXEC sp_add_log_shipping_primary_database
  @database = 'OrdersDB',
  @backup_directory = '\\backupserver\logs',
  @backup_share = '\\backupserver\logs',
  @backup_job_name = 'LSBackup_OrdersDB',
  @backup_retention_period = 4320, -- 保留3天
  @monitor_server = 'MonitorServer';
-- 辅助服务器设置
EXEC sp_add_log_shipping_secondary_database
  @secondary_database = 'OrdersDB',
  @primary_server = 'PrimaryServer',
  @primary_database = 'OrdersDB',
  @restore_delay = 0, -- 立即还原
  @restore_mode = 1; -- 待机/只读模式
成败关键:
-
RPO = 日志备份间隔(通常15-30分钟)
-
RTO = 手动故障转移时间(可能10-60分钟)
-
辅助库可用于报表查询(在还原期间短暂中断)
5. Always On 可用性组(AG)
核心概念:
| 概念 | 说明 |
|——|——|
| 可用性副本 | 每个SQL Server实例是一个副本(主+最多8个从) |
| 可用性数据库 | AG保护的数据库集合 |
| 同步提交 | 主库等待从库确认日志硬化后才提交(RPO=0) |
| 异步提交 | 主库不等待从库(高性能,可能丢数据) |
| 自动故障转移 | 仅同步提交副本支持 |
| 手动故障转移 | 同步或异步都支持 |
| 只读路由 | 将读请求自动转发到辅助副本 |
| 侦听器 | 虚拟网络名+IP,客户端连接点 |
部署架构示例:
  客户端
  ↓
  可用性组侦听器
  ↓
  ┌─────┴─────┐
  ↓ ↓
  主副本 辅助副本
(同步提交) (同步提交)
  / \ / \
 生产DC1 生产DC2
  ↘ ↙
  异步副本(DR中心)
  (异步提交)
创建AG示例:
-- 创建端点(加密通信)
CREATE ENDPOINT HadrEndpoint
  STATE=STARTED
  AS TCP (LISTENER_PORT=5022)
  FOR DATA_MIRRORING (ROLE=ALL);
-- 创建可用性组
CREATE AVAILABILITY GROUP OrdersAG
  WITH (CLUSTER_TYPE = WSFC) -- Windows故障转移集群
  FOR DATABASE OrdersDB
  REPLICA ON
  'PrimaryServer' WITH (
  ENDPOINT_URL = 'TCP://PrimaryServer:5022',
  AVAILABILITY_MODE = SYNCHRONOUS_COMMIT,
  FAILOVER_MODE = AUTOMATIC
  ),
  'SecondaryServer' WITH (
  ENDPOINT_URL = 'TCP://SecondaryServer:5022',
  AVAILABILITY_MODE = SYNCHRONOUS_COMMIT,
  FAILOVER_MODE = AUTOMATIC
  );
-- 添加侦听器
ALTER AVAILABILITY GROUP OrdersAG
  ADD LISTENER 'OrdersAG_Listener' (
  WITH IP (('192.168.1.100', '255.255.255.0')),
  PORT=1433
  );
关键限制:
-
一个AG最多9个副本(1主+8从)
-
每个数据库只能属于一个AG
-
辅助副本不能直接写入(可用只读操作)
-
跨版本有限支持(从库可低于主库两个版本)
监控AG健康:
-- 检查副本状态
SELECT replica_server_name, role_desc, synchronization_health_desc
FROM sys.dm_hadr_availability_replica_states;
-- 检查数据同步延迟
SELECT ag.name, db_name(database_id) as dbname,
  log_send_queue_size, log_send_rate,
  redo_queue_size, redo_rate
FROM sys.dm_hadr_database_replica_states drs
JOIN sys.availability_groups ag ON drs.group_id = ag.group_id;
6. 复制技术(Replication)
三种类型对比:
| 类型 | 数据流向 | 延迟 | 冲突处理 | 适用场景 |
|——|———-|——|———-|———-|
| 快照复制 | 单向 | 高(定时复制)| 无 | 小表,静态数据 |
| 事务复制 | 单向 | 低(秒级)| 无(默认)| 数据分发,报表 |
| 合并复制 | 双向/多向 | 中 | 需要解决 | 移动设备,离线 |
事务复制架构:
发布服务器(Publisher)→ 分发服务器(Distributor)→ 订阅服务器(Subscriber)
  ↓ ↓ ↓
  事务日志读取器 分发数据库 应用更改
创建复制示例:
-- 创建发布(主服务器)
EXEC sp_addpublication
  @publication = 'OrdersPub',
  @description = '发布订单表',
  @sync_method = 'native',
  @repl_freq = 'continuous', -- 连续(事务复制)
  @status = 'active';
-- 添加项目(表)
EXEC sp_addarticle
  @publication = 'OrdersPub',
  @article = 'Orders',
  @source_object = 'Orders',
  @destination_table = 'Orders';
-- 创建订阅(订阅服务器)
EXEC sp_addsubscription
  @publication = 'OrdersPub',
  @subscriber = 'SubscriberServer',
  @destination_db = 'OrdersDB_Sub',
  @status = 'active';
事务复制冲突:
-
中心发布服务器模式:一般无冲突
-
可更新订阅:需要冲突解决策略(发布服务器胜出/订阅服务器胜出/自定义)
7. 技术选型决策树
是否要求自动故障转移?
├─ 是 → 是否允许数据丢失?
│ ├─ 零丢失(RPO=0)→ Always On 同步提交(需要2台以上服务器+见证)
│ └─ 秒级丢失(RPO>0)→ 故障转移集群 或 Always On 异步提交
│
└─ 否 → 是否需要辅助库做报表查询?
  ├─ 是 → 日志传送(简单) 或 Always On 异步(更强)
  ├─ 部分表需要实时 → 事务复制(灵活)
  └─ 移动/离线场景 → 合并复制
需要考虑其他因素:
- 数据库数量:Always On 支持多数据库但每个AG上限有限
- 跨版本:事务复制支持混合版本(2016→2019)
- 跨平台:AG和FCI要求Windows故障转移集群(不支持Linux?现在部分支持)
- 网络延迟:同城<1ms可用同步提交,异地用异步
8. 高可用切换演练关键步骤
计划内切换(Always On):
-- 1. 检查辅助副本状态
SELECT * FROM sys.dm_hadr_database_replica_states;
-- 2. 连接辅助副本准备
ALTER AVAILABILITY GROUP OrdersAG SET (ROLE = SECONDARY);
-- 3. 执行切换(在主副本执行)
ALTER AVAILABILITY GROUP OrdersAG FAILOVER;
-- 4. 验证新主副本
SELECT @@SERVERNAME, DATABASEPROPERTYEX('OrdersDB', 'Updateability');
灾难后强制恢复(日志传送):
-- 1. 备份尾日志(如果主库还可用)
BACKUP LOG OrdersDB TO DISK = '\\backupserver\logs\OrdersDB_tail.trn'
WITH NORECOVERY;
-- 2. 应用所有日志到辅助库
RESTORE LOG OrdersDB FROM DISK = '\\backupserver\logs\orders_20240101.trn'
WITH RECOVERY;
-- 3. 启用辅助库对外服务
ALTER DATABASE OrdersDB SET ONLINE;
-- 4. 重新配置应用连接字符串
9. 常见问题与排查
| 问题 | 常见原因 | 排查方向 |
|——|———-|———-|
| AG切换失败 | 仲裁丢失、健康检查失败 | 查看Windows集群日志,检查sys.dm<em>hadr</em>* |
| 日志传送延迟大 | 网络慢、作业冲突 | 检查复制、还原作业耗时 |
| 复制跳过某些行 | 冲突、数据不一致、约束失败 | 查看复制监视器、分发数据库错误表 |
| 辅助库无法查询 | 正在还原日志、未开启只读 | 设置STANDBY模式或AG读路由 |
| RPO超过预期 | 异步模式、网络高延迟 | 改用同步,或压缩日志备份 |
10. 最佳实践总结
- Always On 为主流首选(SQL Server 2012+):
-
灵活性高(同步/异步,自动/手动)
-
支持多种场景(本地HA+异地DR)
-
从库可用于备份和报表
- 日志传送作为补充:
-
简单易维护,RPO可控
-
适合低成本DR方案
-
可配合AG使用(备份还原延迟保护)
- 复制用于特定需求:
-
数据分发(中心到分支)
-
异构环境(Oracle → SQL Server)
-
实时报表卸载
- 定期演练:
-
每季度一次计划内切换
-
每年一次灾难恢复模拟
-
验证RTO/RPO是否达标
- 监控关键指标:
-
同步延迟(秒)
-
未发送/未还原日志量(KB)
-
集群仲裁状态
-
复制延迟和冲突数
第九期小结
高可用与灾难恢复的选择取决于RTO/RPO要求、预算和运维能力。Always On AG是当前功能最全面的解决方案,支持同步提交实现零数据丢失,异步提交支持异地容灾。日志传送适合预算有限的DR场景,复制则解决特定数据分发问题。无论选择哪种技术,定期演练和健全的监控都是保证故障时能正确恢复的关键。
下期预告:性能监控与调优方法论 —— 从等待统计到DMV分析,如何建立系统化的性能优化流程?