Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

High Availability & Disaster Recovery

Overview: Các yếu tố cần cân nhắc

RPO vs RTO Tradeoffs

Công nghệRPORTOReadable SecondaryTransparent FailoverChi phí
Always On AG (Sync)~0 (zero data loss)< 30 giâyCó (Enterprise)Có (với listener)Cao
Always On AG (Async)Vài giây< 30 giâyCó (Enterprise)ManualCao
FCI~0 (shared storage)1-5 phútKhôngCó (WSFC)Rất cao
Log ShippingVài phút - giờ30-60 phútCó (STANDBY)Không (manual)Thấp
Database Mirroring (deprecated)~0 (Sync)< 30 giâyKhôngCó (với witness)Trung bình
Replication (Transactional)Vài giâyTùyKhôngTrung bình
Azure Auto-failover GroupsVài giây< 1 phútCao

Synchronous vs Asynchronous Replication

Synchronous (Đồng bộ):
  Primary → Commit → Ghi log local → Gửi log đến Secondary
                                    ← Nhận ACK từ Secondary
  → Primary chỉ commit xong khi Secondary đã nhận và hardened log
  → RPO = 0 (zero data loss), nhưng latency tăng theo network

Asynchronous (Bất đồng bộ):
  Primary → Commit → Ghi log local → Return to client
                   → Gửi log đến Secondary (background)
  → Primary không chờ Secondary → latency thấp
  → RPO > 0 (có thể mất vài giây data khi failover)

Always On Availability Groups (AG)

Giải pháp HA cao cấp nhất của SQL Server (Enterprise Edition), cung cấp:

  • Database-level HA (không phải instance-level như FCI)
  • Readable secondaries
  • Automatic failover
  • Hỗ trợ Azure (Hybrid scenarios)

Kiến trúc

                    ┌─────────────────────────────────────┐
                    │     Windows Server Failover Cluster  │
                    │                                      │
  ┌──────────────┐  │  ┌──────────┐      ┌──────────┐    │
  │  Application │──┼─▶│ Listener │      │ WSFC     │    │
  └──────────────┘  │  │ (VNN)    │      │ Quorum   │    │
         │          │  └────┬─────┘      └──────────┘    │
         │          │       │                              │
         │          │  ┌────▼─────────────────────────┐  │
         │          │  │        AG Group               │  │
         │          │  │                               │  │
         │          │  │  ┌──────────┐  ┌──────────┐  │  │
         │          │  │  │ Primary  │  │Secondary │  │  │
         └──────────┼──┤  │ Replica  │◀▶│ Replica  │  │  │
    Read/Write      │  │  │ (Node 1) │  │ (Node 2) │  │  │
                    │  │  └──────────┘  └──────────┘  │  │
                    │  └──────────────────────────────┘  │
                    └─────────────────────────────────────┘

    ┌─────────────────┐      ┌───────────────────┐
    │ Read-Only       │─────▶│ Secondary Replica │
    │ Applications    │      │ (Node 2)          │
    └─────────────────┘      └───────────────────┘

Cấu hình AG cơ bản

-- Trên Primary: Enable AlwaysOn (phải restart SQL Server sau)
-- Thực hiện qua SSMS hoặc PowerShell:
-- Enable-SqlAlwaysOn -ServerInstance "SQL01" -Force

-- Bước 1: Tạo Master Key và Certificate (cho endpoint encryption)
USE master;
CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'StrongP@ssword!';
CREATE CERTIFICATE AG_Cert
WITH SUBJECT = 'AG Endpoint Certificate',
START_DATE = '20260101',
EXPIRY_DATE = '20360101';

-- Bước 2: Tạo Endpoint
CREATE ENDPOINT HADR_endpoint
STATE = STARTED
AS TCP (LISTENER_PORT = 5022, LISTENER_IP = ALL)
FOR DATABASE_MIRRORING (
    AUTHENTICATION = CERTIFICATE AG_Cert,
    ENCRYPTION = REQUIRED ALGORITHM AES,
    ROLE = ALL
);

-- Bước 3: Backup cert để dùng trên secondary
BACKUP CERTIFICATE AG_Cert
TO FILE = '\\Shared\Certs\AG_Cert.cer';

-- Trên Secondary: tạo login, cert, endpoint tương tự

-- Bước 4: Tạo Availability Group (trên Primary)
CREATE AVAILABILITY GROUP [AG_Production]
WITH (
    AUTOMATED_BACKUP_PREFERENCE = SECONDARY,  -- Backup trên secondary
    DB_FAILOVER = ON,  -- Failover khi health check fail
    DTC_SUPPORT = NONE,
    CLUSTER_TYPE = WSFC
)
FOR DATABASE [ProductionDB], [SalesDB]
REPLICA ON
    N'SQL01'
    WITH (
        ENDPOINT_URL = N'TCP://SQL01.domain.com:5022',
        AVAILABILITY_MODE = SYNCHRONOUS_COMMIT,
        FAILOVER_MODE = AUTOMATIC,
        SEEDING_MODE = AUTOMATIC,
        SECONDARY_ROLE (ALLOW_CONNECTIONS = READ_ONLY,
                        READ_ONLY_ROUTING_URL = N'TCP://SQL01.domain.com:1433')
    ),
    N'SQL02'
    WITH (
        ENDPOINT_URL = N'TCP://SQL02.domain.com:5022',
        AVAILABILITY_MODE = SYNCHRONOUS_COMMIT,
        FAILOVER_MODE = AUTOMATIC,
        SEEDING_MODE = AUTOMATIC,
        SECONDARY_ROLE (ALLOW_CONNECTIONS = READ_ONLY,
                        READ_ONLY_ROUTING_URL = N'TCP://SQL02.domain.com:1433')
    );

-- Trên Secondary: join AG
ALTER AVAILABILITY GROUP [AG_Production] JOIN;
ALTER AVAILABILITY GROUP [AG_Production] GRANT CREATE ANY DATABASE;

Monitoring AG Status

-- Xem trạng thái AG
SELECT 
    ag.name AS availability_group,
    ar.replica_server_name,
    ar.availability_mode_desc,
    ar.failover_mode_desc,
    ars.role_desc,
    ars.synchronization_health_desc,
    ars.connected_state_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;

-- Xem log send queue và redo queue
SELECT 
    db_name(drs.database_id) AS database_name,
    drs.log_send_queue_size AS log_send_queue_kb,
    drs.log_send_rate AS log_send_rate_kb_s,
    drs.redo_queue_size AS redo_queue_kb,
    drs.redo_rate AS redo_rate_kb_s,
    drs.synchronization_state_desc
FROM sys.dm_hadr_database_replica_states drs;

-- Manual failover (khi cần maintenance trên Primary)
ALTER AVAILABILITY GROUP [AG_Production] FAILOVER;

Availability Group Listener

-- Tạo listener (sau khi AG đã tạo)
ALTER AVAILABILITY GROUP [AG_Production]
ADD LISTENER N'AG_Listener' (
    WITH IP ((N'192.168.1.100', N'255.255.255.0')),
    PORT = 1433
);

-- Connection string dùng listener (ứng dụng kết nối đến đây, không quan tâm Primary là node nào)
-- "Server=AG_Listener,1433;Database=ProductionDB;Integrated Security=True;
--  ApplicationIntent=ReadWrite;MultiSubnetFailover=True"

-- Read-only routing (kết nối ReadOnly → tự động redirect đến secondary)
-- "Server=AG_Listener,1433;Database=ProductionDB;Integrated Security=True;
--  ApplicationIntent=ReadOnly"

-- Cấu hình read-only routing list
ALTER AVAILABILITY GROUP [AG_Production]
MODIFY REPLICA ON N'SQL01'
WITH (PRIMARY_ROLE (
    READ_ONLY_ROUTING_LIST = (N'SQL02', N'SQL01')  -- Ưu tiên SQL02 cho read
));

ALTER AVAILABILITY GROUP [AG_Production]
MODIFY REPLICA ON N'SQL02'
WITH (PRIMARY_ROLE (
    READ_ONLY_ROUTING_LIST = (N'SQL01', N'SQL02')
));

Always On Failover Cluster Instances (FCI)

Instance-level HA, khác với AG (database-level).

                    ┌─────────────────────────────────────┐
                    │   Windows Server Failover Cluster    │
                    │                                      │
  ┌──────────────┐  │  ┌──────────┐     ┌──────────┐     │
  │  Application │──┼─▶│  VNN     │     │  WSFC    │     │
  └──────────────┘  │  │ (Virtual │     │  Quorum  │     │
                    │  │ Network  │     └──────────┘     │
                    │  │  Name)   │                       │
                    │  └────┬─────┘                       │
                    │       │                              │
                    │  ┌────▼────────────────────────┐   │
                    │  │  SQL Server FCI Instance    │   │
                    │  │                             │   │
                    │  │  ┌──────────┐ ┌──────────┐ │   │
                    │  │  │  Node 1  │ │  Node 2  │ │   │
                    │  │  │ (Active) │ │(Passive) │ │   │
                    │  │  └────┬─────┘ └──────────┘ │   │
                    │  │       │                     │   │
                    │  │  ┌────▼──────────────────┐ │   │
                    │  │  │    Shared Storage      │ │   │
                    │  │  │ (SAN / Azure Shared   │ │   │
                    │  │  │  Disk / S2D)           │ │   │
                    │  │  └───────────────────────┘ │   │
                    │  └────────────────────────────┘   │
                    └─────────────────────────────────────┘

Đặc điểm FCI:

  • Tất cả nodes chia sẻ cùng một storage
  • Chỉ một node Active tại một thời điểm
  • Failover: SQL Server instance chuyển sang node khác (shared storage vẫn accessible)
  • Không có readable secondary
  • Protect toàn bộ SQL Server instance (tất cả databases, SQL Agent jobs, logins)
  • License: chỉ cần license cho active nodes

Log Shipping

Giải pháp HA đơn giản, chi phí thấp — automated backup → copy → restore.

  ┌─────────────┐    Backup Log     ┌─────────────┐
  │   Primary   │─────────────────▶ │   Monitor   │
  │   (Source)  │                   │   Server    │
  └──────┬──────┘                   └──────┬──────┘
         │                                  │
         │ Backup files (shared folder)     │ Alert if delay
         │                                  │
         ▼                                  ▼
  ┌──────────────┐    Copy + Restore  ┌──────────────┐
  │  .trn files  │──────────────────▶ │  Secondary   │
  │  (Share)     │                   │  (DR Server) │
  └──────────────┘                   └──────────────┘
-- Cấu hình Log Shipping qua SSMS hoặc T-SQL
-- Primary: setup backup job
-- Primary database phải ở FULL recovery model

EXEC master.dbo.sp_add_log_shipping_primary_database
    @database = N'ProductionDB',
    @backup_directory = N'\\BackupShare\LogShipping',
    @backup_share = N'\\BackupShare\LogShipping',
    @backup_job_name = N'LSBackup_ProductionDB',
    @backup_retention_period = 4320,  -- 3 days (minutes)
    @backup_threshold = 60,  -- Alert nếu backup delay > 60 phút
    @threshold_alert_enabled = 1,
    @history_retention_period = 5760;  -- Keep history 4 days

-- Secondary: setup copy + restore jobs
EXEC master.dbo.sp_add_log_shipping_secondary_database
    @secondary_database = N'ProductionDB',
    @primary_server = N'SQL01',
    @primary_database = N'ProductionDB',
    @restore_delay = 0,
    @restore_mode = 0,          -- 0 = NORECOVERY, 1 = STANDBY (readable)
    @disconnect_users = 0,
    @restore_threshold = 45,    -- Alert nếu restore delay > 45 phút
    @threshold_alert_enabled = 1,
    @history_retention_period = 5760;

-- Xem trạng thái Log Shipping
SELECT 
    primary_database,
    backup_threshold,
    time_since_last_backup,
    last_backup_file
FROM msdb.dbo.log_shipping_monitor_primary;

SELECT 
    secondary_database,
    restore_threshold,
    time_since_last_restore,
    last_restored_file
FROM msdb.dbo.log_shipping_monitor_secondary;

Standby Mode: Secondary Read-Only

-- Restore với STANDBY: secondary database read-only (nhưng disconnect khi restore job chạy)
RESTORE LOG ProductionDB
FROM DISK = 'D:\LogShipping\ProductionDB_Log.trn'
WITH STANDBY = 'D:\LogShipping\Standby_Undo.bak';
-- Database trở thành read-only, users có thể query
-- Khi job restore log kế tiếp: disconnect users, apply log, back to read-only

Database Mirroring (Deprecated nhưng vẫn được hỏi)

Lưu ý: Deprecated từ SQL Server 2012, removed trong Azure SQL. Dùng AG thay thế.

  ┌──────────────┐  sync/async  ┌──────────────┐
  │  Principal   │◀────────────▶│    Mirror    │
  │  (Primary)   │              │  (Secondary) │
  └──────┬───────┘              └──────────────┘
         │                              │
         └──────────────────────────────┤
                        │               │
                   ┌────▼────┐          │
                   │ Witness │◀─────────┘
                   │(optional│
                   │for auto │
                   │failover)│
                   └─────────┘
ModeÝ nghĩa
High Safety (Synchronous)+ Witness → Automatic failover; không có witness → Manual
High Performance (Asynchronous)Không có witness, manual failover, có thể mất data

Replication

Sao chép dữ liệu giữa databases — không phải HA mà là data distribution.

  ┌─────────────┐  ┌──────────────┐  ┌─────────────┐
  │  Publisher  │─▶│ Distributor  │─▶│ Subscriber  │
  │   (Source)  │  │  (Metadata + │  │ (Destination│
  │             │  │   queue)     │  │    copy)    │
  └─────────────┘  └──────────────┘  └─────────────┘

So sánh các loại Replication

LoạiHoạt độngRPOUse Case
SnapshotCopy toàn bộ data định kỳHoursLookup tables, ít thay đổi
TransactionalStream từng transactionGiâyReal-time reporting, OLAP offload
MergeSync 2 chiều, conflict resolutionPhútMobile, distributed updates
Peer-to-PeerMulti-master transactionalGiâyGeo-distributed OLTP (phức tạp)
-- Xem replication status
SELECT * FROM distribution.dbo.MSdistribution_status;

-- Check replication latency (để monitor)
-- Thêm tracer token
EXEC sp_posttracertoken
    @publication = N'MyPublication',
    @tracer_token_syntax = N'This is a tracer token %s',
    @publisher_db = N'PublisherDB';

Azure SQL High Availability

Built-in HA (PaaS)

Azure SQL Database / Managed Instance có HA built-in — không cần cấu hình:

  • General Purpose / Standard: storage-level redundancy, failover ~30 giây
  • Business Critical / Premium: AG-like, local SSD, readable secondaries, failover < 30 giây
  • Hyperscale: scale-out reads với nhiều read replicas

Active Geo-Replication

-- Tạo readable secondary ở region khác (Azure SQL Database)
-- Thực hiện qua Azure Portal hoặc PowerShell:
-- New-AzSqlDatabaseSecondary -ResourceGroupName "rg1" 
--     -ServerName "primaryserver" -DatabaseName "mydb"
--     -PartnerResourceGroupName "rg2" -PartnerServerName "secondaryserver"

-- Failover thủ công
-- Set-AzSqlDatabaseSecondary -ResourceGroupName "rg2"
--     -ServerName "secondaryserver" -DatabaseName "mydb" -Failover

-- Hoàn toàn qua T-SQL với ALTER DATABASE (trong Azure SQL)
ALTER DATABASE mydb FAILOVER;

Auto-failover Groups

-- Auto-failover group: wrapper trên geo-replication + listener endpoint
-- Connection string: không cần biết primary/secondary
-- "Server=group-name.database.windows.net;Database=mydb;..."
-- Read-only: "Server=group-name.secondary.database.windows.net;..."

Database Snapshots như một cơ chế bảo vệ tạm thời

-- Tạo snapshot trước khi maintenance lớn
CREATE DATABASE ProductionDB_PreMaintenance
ON (NAME = 'ProductionDB_Data',
    FILENAME = 'D:\Snapshots\ProdDB_PreMaintenance.ss')
AS SNAPSHOT OF ProductionDB;

-- Sau maintenance nếu có vấn đề → revert
RESTORE DATABASE ProductionDB
FROM DATABASE_SNAPSHOT = 'ProductionDB_PreMaintenance';

-- Snapshot KHÔNG phải backup thực sự:
-- - Phụ thuộc source database
-- - Không protect khỏi server failure
-- - Không thể backup/restore riêng lẻ

Q&A - Phỏng vấn High Availability

Junior Level

Q1: Always On AG và FCI khác nhau thế nào?

Always On AGFCI
ScopeDatabase-levelInstance-level
StorageMỗi replica có storage riêngShared storage
Readable secondaryCó (Enterprise)Không
LicensePer-core tất cả replicasChỉ active nodes
Failover granularityTừng database/AGToàn bộ instance

Q2: Log Shipping là gì? Khi nào nên dùng?

Log Shipping tự động backup transaction log từ Primary, copy sang Secondary server, và restore. Secondary ở NORECOVERY hoặc STANDBY (read-only).

Dùng khi: ngân sách hạn chế, RPO 15-60 phút là chấp nhận được, cần readable DR server. Không dùng khi cần RPO gần zero hoặc automatic failover.

Q3: Sự khác biệt giữa synchronous và asynchronous AG?

  • Synchronous: Primary chờ Secondary hardened log trước khi commit → RPO = 0, nhưng độ trễ tăng (chỉ dùng trong cùng datacenter hoặc low-latency WAN)
  • Asynchronous: Primary không chờ Secondary → RPO > 0 (có thể mất vài giây data), nhưng không ảnh hưởng latency → dùng cho geo-distributed DR replicas

Mid Level

Q4: Readable Secondary trong AG hoạt động thế nào? Có vấn đề gì?

Secondary replica apply log từ Primary. Khi nhận log nhưng chưa apply, queries trên secondary đọc data cũ → potential dirty reads? Không — secondary dùng row versioning (snapshot isolation) để queries đọc consistent snapshot, không block redo operations.

Vấn đề:

  • Snapshot isolation sử dụng tempdb trên secondary → monitor tempdb usage
  • Queries nặng trên secondary có thể ảnh hưởng redo process (thường không đáng kể)
  • Data có thể lag vài milliseconds so với Primary

Q5: AG Listener làm gì? Transparent failover hoạt động thế nào?

Listener là Virtual Network Name (VNN) hoặc Distributed Network Name (DNN) — application kết nối đến Listener, không kết nối trực tiếp đến node. Khi failover:

  1. Secondary become Primary
  2. Listener routing update (< vài giây với DNN)
  3. Application reconnect đến Listener → tự động kết nối đến Primary mới

Application phải handle reconnection (retry logic). Connection string cần MultiSubnetFailover=True để reconnect nhanh trong multi-subnet AG.

Q6: Khi nào chọn Always On AG vs Azure Active Geo-Replication?

  • On-premises / SQL Server trong VM: Always On AG
  • Azure SQL Database: Active Geo-Replication hoặc Auto-failover Groups (PaaS, managed)
  • Azure SQL Managed Instance: Auto-failover groups (AG built-in, managed)
  • Hybrid (on-prem + Azure): AG với Azure replica (Disaster Recovery to Azure)

Senior Level

Q7: Thiết kế HA/DR solution cho ứng dụng banking: RPO = 0, RTO < 1 phút, có DR site?

Solution:

  • Primary DC: Always On AG với 2 nodes, synchronous commit, automatic failover
    • Node 1: Primary
    • Node 2: Synchronous secondary (same DC, auto failover)
  • DR DC: Node 3, asynchronous commit (cross-DC, RPO = vài giây)
  • Windows Server Failover Cluster: spanning cả 2 DCs
  • Listener: DNN (vì DNN nhanh hơn VNN khi failover)

RPO:

  • Trong cùng DC (Node 1 → 2): RPO = 0 (synchronous)
  • DR failover (Node 1/2 → 3): RPO = vài giây (asynchronous)

RTO:

  • Trong DC: < 30 giây (automatic failover)
  • DR failover: < 1 phút (manual hoặc WSFC cross-DC failover)

Q8: AG split-brain scenario là gì? WSFC quorum giải quyết thế nào?

Split-brain: Hai nodes mất kết nối với nhau nhưng cả hai đều nghĩ mình là Primary → cả hai process writes → data divergence.

WSFC Quorum ngăn chặn split-brain: một node/cluster chỉ active khi đạt quorum (majority):

  • Node Majority: > 50% nodes votes
  • Node and File Share Majority: nodes + file share witness vote
  • Node and Disk Majority: nodes + disk witness vote
  • Cloud Witness (SQL Server 2016+): Azure Blob Storage làm witness

Nếu một DC bị cô lập và không đạt quorum → nodes đó tự shut down SQL Server → không thể process writes → no split-brain.

Q9: Làm thế nào để achieve zero-downtime maintenance trên AG Primary?

Planned maintenance (patch, hardware):

  1. Force failover to secondary (pre-check secondary health)
  2. Thực hiện maintenance trên node cũ (giờ là secondary)
  3. Về sau failover lại về original node (nếu cần)
  4. Với read-only routing: ứng dụng đọc không bị ảnh hưởng

Online maintenance options:

  • Index rebuild với ONLINE = ON: không block reads/writes
  • Index maintenance per-partition: không cần lock toàn bảng
  • Statistics update: ASYNC_STATS_UPDATE (SQL Server 2017+)
  • Schema changes: cần test carefully, có thể cần maintenance window