SQL Server 資料庫鏡像高可用性模式 (Principal + Mirror + Witness) 依賴三節點心跳機制。預設 `PARTNER_TIMEOUT = 10` 秒,意味著任一心跳超過 10 秒未收到即判定失效、觸發故障轉移。在跨資料中心、虛擬化環境、網路擁塞場景下,10 秒極易誤觸發。本文詳細說明調整機制、風險權衡、最佳實踐與驗證方法。
Principal ←──PING──→ Mirror
│ │
└──────PING─────────┘
│
Witness
-- 設定為 20 秒
ALTER DATABASE [YourDB] SET PARTNER TIMEOUT 20;
-- 查詢目前值
SELECT mirroring_partner_timeout FROM sys.database_mirroring WHERE database_id = DB_ID('YourDB');
| Timeout 值 | 誤觸發風險 | 真實故障轉移延遲 | RTO 影響 | 適用場景 |
|---|---|---|---|---|
| 5 秒 (最小) | 極高 | 最快 | 最低 | 極穩定 LAN、物理機直連 |
| 10 秒 (預設) | 中等 | 快 | 低 | 一般企業 LAN、低延遲環境 |
| 20-30 秒 | 低 | 中等 | 中等 | 跨機房、虛擬化、網路偶發擁塞 |
| 45-60 秒 | 極低 | 慢 | 高 | 跨城/跨雲、高延遲、不穩定網路 |
核心權衡:Timeout 每增加 1 秒,真實故障時的 RTO 就增加 1 秒。在「網路抖動頻率」與「可容忍 RTO」之間找平衡點。
-- 收集 7 天心跳往返時間 (RTT) 分布
-- 方法:Extended Events 捕獲 database_mirroring_state_change / 手動 ping 記錄
SELECT
AVG(rtt_ms) AS AvgRTT,
PERCENTILE_CONT(0.99) WITHIN GROUP (ORDER BY rtt_ms) OVER () AS P99RTT,
MAX(rtt_ms) AS MaxRTT
FROM HeartbeatLog
WHERE log_date >= DATEADD(DAY, -7, GETDATE());
-- 即時監控鏡像狀態與延遲
SELECT
DB_NAME(database_id) AS DBName,
mirroring_state_desc,
mirroring_role_desc,
mirroring_partner_timeout AS TimeoutSec,
mirroring_witness_state_desc,
mirroring_connection_timeout AS WitnessTimeout
FROM sys.database_mirroring
WHERE mirroring_guid IS NOT NULL;
-- 告警:狀態非 SYNCHRONIZED 持續 > 1 分鐘
資料庫鏡像已進入維護模式 (Deprecated since SQL 2012)。新架構請直接採用 AlwaysOn 可用性群組 (AG)。
| 特性 | Database Mirroring | AlwaysOn AG |
|---|---|---|
| 多資料庫故障轉移 | 單庫獨立,需協調機制 | 群組級原子故障轉移 |
| 唯讀副本 | 不支援 (需快照) | 支援多個可讀次要副本 |
| 故障轉移超時控制 | PARTNER_TIMEOUT (單一值) | 靈活的租約機制 + 租約超時設定 |
| 跨子網支援 | 複雜 (需多 IP OR 邏輯) | 原生 MultiSubnetFailover |
| 版本支援 | SQL 2005-2017 (Deprecated) | SQL 2012+ (標準版/企業版) |
`PARTNER_TIMEOUT` 是資料庫鏡像在不穩定網路下的「緩衝器」。調整原則:測量實際 RTT 分布 → 設定 ≥ P99×3 → 三方協同調整 → 持續監控 → 規劃遷移 AG。不要為了追求極致 RTO 而設定過低 Timeout,導致頻繁誤故障轉移,反而降低可用性。