将 Microsoft SQL Server 从 AWS 迁移到 Google Cloud

Last reviewed 2023-05-05 UTC

本文档介绍如何将 Amazon Elastic Compute Cloud (Amazon EC2) 上安装的 Microsoft SQL Server 实例迁移到 Google Cloud 中 Compute Engine 上的 Microsoft SQL Server 实例。此迁移仅基于 Microsoft SQL Server 提供的内置数据库技术。此方法实际上是使用 Always On 可用性组的零停机时间方法。Always On 可用性组通过 VPN 与 AWS 和 Google Cloud 连接,并且允许复制 Microsoft SQL Server 数据库。本文假定您熟悉网络设置、Google Cloud、Compute Engine、AWS 和 Microsoft SQL Server。

如果您只想执行复制,可以按照本教程中的步骤执行操作,但要在添加测试数据并省略切换步骤后停止。

目标

  • 部署一个多云端 Microsoft SQL Server Always On 可用性组,它涵盖 Amazon EC2 中的 Microsoft SQL Server 和 Compute Engine 上的 Google Cloud 中 Microsoft SQL Server。
  • 在 Amazon EC2 中设置主 Microsoft SQL 实例。
  • 在 Google Cloud 中将 Microsoft SQL Server 实例设置为 AWS 中主要 Microsoft SQL Server 的次要数据库(数据复制目标)。
  • 通过在 Google Cloud 中将次要 Microsoft SQL Server 设置为 Google Cloud 中的主 Microsoft SQL Server,完成数据迁移。

费用

在本文档中,您将使用 Google Cloud 的以下收费组件:

您可使用价格计算器根据您的预计使用情况来估算费用。 Google Cloud 新用户可能有资格申请免费试用

本教程还要求 AWS 中的资源可能会产生费用。

准备工作

  1. 在 Google Cloud Console 中的项目选择器页面上,选择或创建一个 Google Cloud 项目

    转到“项目选择器”

  2. 确保您的 Google Cloud 项目已启用结算功能

  3. 在 Google Cloud 控制台中,激活 Cloud Shell。

    激活 Cloud Shell

了解数据库迁移

数据库迁移将数据从源数据库转移到目标数据库。通常,您可以迁移部分数据,也可以在源数据库和目标数据库中使用不同的架构。但是,本教程解决了需要迁移完整数据库而不需要更改的数据库迁移—目标数据库是源数据库的副本。

零停机时间数据库迁移

零停机时间指在迁移期间,访问源数据库的客户端将继续保持运行状态,不会中断。只有在迁移完成后客户端必须重新连接到目标数据库,才会发生停机。虽然这种方法不会造成零停机时间,但该术语指最小停机时间。

有关数据库迁移的一般讨论,请参阅数据库迁移 - 概念和原则(第 1 部分)数据库迁移 - 概念和原则(第 2 部分)。这些文章概述了数据库在不同场景中的复杂性。

使用 Microsoft SQL Server 技术迁移数据库

某些数据库迁移技术提供独立的组件和服务。当数据库迁移需要源数据库的副本时,您可以使用内置的 Microsoft SQL Server 技术。

本教程使用 Microsoft SQL Server Always On 可用性组技术将源数据库(主数据库)连接到目标数据库(次要)。这项技术提供从主数据库到次要数据库的异步复制。由于主数据库位于 Amazon EC2 中,而次要数据库位于 Compute Engine 上的 Google Cloud 中,因此复制会涉及数据库迁移。通过异步复制迁移所有数据后,次要服务器会提升到主实例,以便客户端重新连接到新的主实例以继续处理。

此方法支持通过对测试目标数据库进行测试复制来明确测试:您可以启动复制,让测试运行一段时间,然后停止复制。测试目标数据库处于一致的状态,您可以使用它测试应用。测试完成后,您可以删除测试目标数据库,然后启动对活跃数据库的复制。

多云端数据库迁移架构

下图显示了多云端数据库迁移的整体部署架构:

Always On 可用性组将 AWS 数据库连接到 Google Cloud 数据库。

上图显示了 AWS 中的源(主)SQL Server 数据库作为 Amazon EC2 实例。该图还显示了 Google Cloud 中的目标数据库(辅助)。数据库通过 Always On 可用性组连接。AWS 和 Google Cloud 之间的网络连接假定为安全的 HA VPN 连接

设置多云端 Microsoft SQL Server 可用性组

在以下部分中,您设置了两个节点 Always On 可用性组,其中主节点位于 AWS 中,辅助节点位于 Google Cloud 中。本文档前面的多云端数据库迁移架构中介绍了此配置。

下表汇总了您在本教程中设置的节点和 IP 地址。对于每个数据库虚拟机,除了主要 IP 地址之外,您还需要分配两个 IP 地址:一个用于 Windows Server 故障切换集群 (WSFC) 的 IP 地址,可用性组监听器分配一个 IP 地址。

提供方 实例 主要 IP WSFC 和可用性组监听器 IP WSFC 可用性组
AWS cluster-sql1 192.168.1.4 192.168.1.5
192.168.1.6
Name: cluster-dbclus Name: cluster-ag
Listener: ag-listener
Google Cloud cluster-sql2 10.1.1.4 10.1.1.5
10.1.1.6
提供方 实例 主要 IP
AWS dc-windows 192.168.1.100 Domain controller

说明使用这些名称和 IP 地址作为示例。如果您要使用自己的名称和 IP 地址,请替换说明中的示例值。

AWS 的前提条件

在 AWS 上,您应该有两个虚拟机:一个运行网域控制器,另一个运行 SQL Server。本教程中用作示例的网域控制器具有以下配置:

Domain                    : dbeng.com
Domain controller         : Name: dc-windows
                            Private IP: 192.168.1.100
VPC Subnet                : 192.168.1.0/24
SQL Server service account: dbeng\sql_service

本教程中使用的 SQL Server 虚拟机是 Amazon EC2 中 Windows Active Directory 网域的一部分。服务器有两个可供 WSFC 和可用性组监听器使用的次要 IP 地址。SQL Server 虚拟机具有以下配置:

VM Instance : Name: cluster-sql1
              Private IP: 192.168.1.4
              Secondary Private IPs: 192.168.1.5, 192.168.1.6
VPC Subnet  : 192.168.1.0/24

您可以使用服务账号 NT SERVICE\MSSQLSERVER 作为 SQL Server 服务账号。在 Always On 可用性组设置过程中,您可以向机器账号(dbeng\cluster-sql1$dbeng\cluster-sql2$)而不是网域账号授予访问权限。以下部分提供了配置可用性组的命令。

AWS 和 Google Cloud 之间连接的前提条件

如需将您的 AWS 项目与 Google Cloud 项目关联,请设置以下网络连接:

  1. 在相应的项目中设置 Google 虚拟私有云和 AWS VPC,并在 VPC 之间配置 VPN。如需了解如何在 Google Cloud 和 AWS 之间设置 VPN,请参阅多云端 VPN 和多地区子网 - 多云端数据库部署的网络设置
  2. 在 Cloud Shell 中,在要在其中创建 SQL Server 实例的 Google Cloud 项目中创建子网。如果您已拥有子网,则可以使用该子网,但务必在下一步中设置防火墙规则。

    gcloud compute networks create demo-vpc --subnet-mode custom
    
    gcloud compute networks subnets create demo-subnet1 \
      --network demo-vpc --region us-east4 --range 10.1.1.0/24
    

    本教程使用以下值:

    • VPC:demo-vpc
    • 子网:demo-subnet1; 10.1.1.0/24

    该子网显示在 Google Cloud 控制台的 VPC 网络页面上。

  3. 在 Google Cloud 项目中,创建防火墙规则,打开 Google Cloud 子网和 AWS 子网之间的所有流量:

    gcloud compute firewall-rules create allow-vpn-ports \
      --network demo-vpc --allow tcp:1-65535,udp:1-65535,icmp \
      --source-ranges 10.1.1.0/24,192.168.1.0/24
    

    防火墙规则显示在 Google Cloud 控制台的防火墙政策页面上。

  4. 在 AWS 项目中,在安全组中创建一个防火墙规则,用于打开 Google Cloud 子网和 AWS 子网之间的所有流量,如以下屏幕截图所示:

    AWS 入站规则设置为允许所有流量、所有协议和所有端口范围。

    在生产环境中,您可以考虑仅打开所需的 TCP/UDP 端口。仅打开必要的端口会限制潜在的有害流量并遵循最低必要的原则。

在 Google Cloud 中为 Always On 可用性组创建实例

本教程支持以下 Microsoft SQL Server 版本和功能:

  • 版本
    • Microsoft SQL Server 2016 Enterprise Edition 或
    • Microsoft SQL Server 2017 Enterprise Edition 或
    • Microsoft SQL Server 2019 Enterprise Edition 或
    • Microsoft SQL Server 2022 Enterprise Edition 或
    • Microsoft SQL Server 2016 Standard Edition
    • Microsoft SQL Server 2017 Standard Edition
    • Microsoft SQL Server 2019 Standard Edition 或
    • Microsoft SQL Server 2022 Standard Edition
  • 功能:Always On 可用性组

以下说明使用 Microsoft SQL Server 2019 Enterprise 版本的映像:sql-ent-2019-win-2019。如果要安装 Microsoft SQL Server 2017、2016 或 2022 Enterprise 版本,请分别改用 sql-ent-2017-win-2019sql-ent-2016-win-2019sql-ent-2022-win-2019。如需查看所有映像的列表,请参阅 Compute Engine 操作系统详细信息页面。

在以下步骤中,您将在 Google Cloud 中为可用性组创建 SQL Server 实例。该实例使用以下 IP 地址配置和别名 IP 地址:

VM Instance: Name: cluster-sql2
             Private IP: 10.1.1.4
             Secondary Private IPs: 10.1.1.5, 10.1.1.6

您可以通过公共 SQL Server 映像创建一个名为 cluster-sql2 的实例,该实例启动磁盘大小达到 200 GB,机器类型为 n1-highmem-4。与网域控制器实例相比,SQL Server 实例通常需要更多的计算资源。如果您日后需要额外的计算资源,可以更改这些实例的机器类型。如果您需要额外的存储空间,请添加一个磁盘或调整永久性启动磁盘的大小。在较大的可用性组中,您可以创建多个实例。

以下步骤还包括在实例创建期间运行 Microsoft PowerShell 命令的 --metadata sysprep-specialize-script-ps1 标志,以安装故障切换集群功能。

  1. 在 Cloud Shell 中,在 Google Cloud 中创建使用与 AWS 相同操作系统版本的 SQL Server 实例:

    gcloud compute instances create cluster-sql2 --machine-type n1-highmem-4 \
      --boot-disk-type pd-ssd --boot-disk-size 200GB \
      --image-project windows-sql-cloud --image-family sql-ent-2019-win-2019 \
      --zone us-east4-a \
      --network-interface "subnet=demo-subnet1,private-network-ip=10.1.1.4,aliases=10.1.1.5;10.1.1.6" \
      --can-ip-forward \
      --metadata sysprep-specialize-script-ps1="Install-WindowsFeature Failover-Clustering -IncludeManagementTools;"
    
  2. 在连接到实例之前,设置 Windows 用户名和密码

  3. 使用笔记本电脑的远程桌面协议 (RDP) 时,请创建允许访问实例的防火墙规则

  4. 使用 RDP 连接到 Google Cloud 实例,并打开提升权限的 PowerShell(以管理员身份运行)。

  5. 在本教程中,您将本地 DNS 配置为使用 AWS (192.168.1.100) 中的网域控制器,以避免在 Google Cloud 中创建另一个虚拟机。对于生产工作负载,我们建议您使用 Google Cloud 中的网域控制器(主要或次要)来避免通过 VPN 隧道进行身份验证。

    在提升权限的 PowerShell 中,您应能对网域控制器 192.168.1.100 执行 ping 操作:

    ping 192.168.1.100
    

    如果 ping 失败,请确保如本文前面的连接先决条件中所述,正确配置 AWS 与 Google Cloud 之间的防火墙和 VPN 隧道。

  6. 由于服务器最初使用 DHCP 进行设置,请将实例更改为使用静态 IP 地址:

    netsh interface ip set address name=Ethernet static 10.1.1.4 255.255.255.0 10.1.1.1 1
    

    运行上述命令后,您的连接会断开。在 RDP 中重新连接。

  7. 将本地 DNS 配置为使用 AWS 中的网域控制器,并为 SQL Server 打开本地防火墙端口。打开防火墙端口,让 SQL Server 连接到远程 SQL Server。

    netsh interface ip set dns Ethernet static 192.168.1.100
    
    netsh advfirewall firewall add rule name="Open Port 5022 for Availability Groups" dir=in action=allow protocol=TCP localport=5022
    
    netsh advfirewall firewall add rule name="Open Port 1433 for SQL Server" dir=in action=allow protocol=TCP localport=1433
    
  8. 将实例添加到 Windows 网域:

    Add-Computer -DomainName "dbeng.com" -Credential "dbeng.com\Administrator" -Restart -Force
    

    该命令会提示您输入网域管理员凭据。当命令运行完毕后,实例会重启。

    如果该命令未运行,请确保以管理员身份运行。

  9. 使用 dbeng\Administrator 账号通过 RDP 重新连接您的实例。

  10. 设置 SQL Server 服务账号:

    1. 打开 SQL Server 2019 配置管理器。
    2. SQL Server Services 标签页中,右键点击 SQL Server (MSSQLSERVER),然后点击属性
    3. dbeng\sql_service 设置账号和密码。
    4. 重新启动 SQL Server。
  11. 重命名 SQL Server 实例以匹配计算机名称并重启 SQL Server:

    Invoke-Sqlcmd -Query "EXEC sp_dropserver @@SERVERNAME, @droplogins='droplogins'"
    
    Invoke-Sqlcmd -Query "EXEC sp_addserver '$env:COMPUTERNAME', local"
    
    Stop-Service -Name "MSSQLServer" -Force
    
    Start-Service -Name "MSSQLServer"
    

接下来,您将在 AWS 中配置该实例。

在 AWS 中配置实例

本教程假定您已在 AWS 中配置以下内容:

  • SQL Server 实例是 Active Directory 网域的一部分。
  • 本地 DNS 正常运行,Google Cloud 中远程服务器的名称(cluster-sql2.dbeng.com) 可以转换为 IP 地址)。
  • 防火墙规则在 AWS 和 Google Cloud 上的子网之间打开。

如需在 AWS 中配置 cluster-sql1,请执行以下操作:

  1. 使用 RDP(cluster-sql1)连接到 AWS。
  2. 打开提升权限的 PowerShell(以管理员身份运行)。
  3. 若其尚未安装,则安装 Windows 故障切换集群。

    Install-WindowsFeature Failover-Clustering -IncludeManagementTools
    

    如果没有安装此功能,则需要重新启动此命令。重启后,请继续执行下一步操作。

  4. 在 AWS 中打开 SQL Server 实例的本地防火墙端口:

    netsh advfirewall firewall add rule name="Open Port 5022 for Availability Groups" dir=in action=allow protocol=TCP localport=5022
    
    netsh advfirewall firewall add rule name="Open Port 1433 for SQL Server" dir=in action=allow protocol=TCP localport=1433
    
    netsh advfirewall firewall add rule name="ICMP Allow incoming V4 echo request" protocol="icmpv4:8,any" dir=in action=allow
    
  5. 重命名 SQL Server 实例以匹配计算机名称并重启 SQL Server:

    Invoke-Sqlcmd -Query "EXEC sp_dropserver @@SERVERNAME, @droplogins='droplogins'"
    
    Invoke-Sqlcmd -Query "EXEC sp_addserver '$env:COMPUTERNAME', local"
    
    Stop-Service -Name "MSSQLServer" -Force
    
    Start-Service -Name "MSSQLServer"
    
  6. 验证 AWS 中使用远程实例名称时可连接至 Google Cloud 中实例的实例。如需测试连接,请从已授予 SQL Server 连接访问权限的网域账号运行以下命令。

    1. 测试网络连接:

      ping -4 cluster-sql2.dbeng.com
      

      输出如下所示:

      RESULTS:
      Pinging cluster-sql2.dbeng.com [10.1.1.4] with 32 bytes of data:
      Reply from 10.1.1.4: bytes=32 time=3ms TTL=127
      Reply from 10.1.1.4: bytes=32 time=2ms TTL=127
      Reply from 10.1.1.4: bytes=32 time=2ms TTL=127
      Reply from 10.1.1.4: bytes=32 time=2ms TTL=127
      
    2. 测试远程服务器的 Windows 身份验证:

      sqlcmd -E -S cluster-sql2.dbeng.com -Q "SELECT 'CONNECTED'"
      

      输出如下所示:

      RESULTS:
      --------------------------------------------------------------------------
      CONNECTED
      
      (1 rows affected)
      

    如果您无法连接,请确保 DNS 正常运行,并且 AWS 和 Google Cloud 子网之间打开了防火墙规则。

验证 Google Cloud 实例已准备好加入可用性组

  1. 使用 dbeng\Administrator 账号通过 RDP (cluster-sql2) 连接到 Google Cloud 实例。
  2. 打开提升权限的 PowerShell(以管理员身份运行)。
  3. 验证 Google Cloud 中的实例在使用实例名称时可连接到 AWS 中的实例。如需测试连接,请从已授予 SQL Server 连接访问权限的网域账号运行以下命令。

    1. 测试网络连接:

      ping -4 cluster-sql1.dbeng.com
      

      输出如下所示:

      RESULTS:
      Pinging CLUSTER-SQL1.dbeng.com [192.168.1.4] with 32 bytes of data:
      Reply from 192.168.1.4: bytes=32 time=3ms TTL=127
      Reply from 192.168.1.4: bytes=32 time=2ms TTL=127
      Reply from 192.168.1.4: bytes=32 time=3ms TTL=127
      Reply from 192.168.1.4: bytes=32 time=2ms TTL=127
      
    2. 测试远程服务器的 Windows 身份验证:

      sqlcmd -E -S cluster-sql1 -Q "SELECT 'CONNECTED'"
      

      输出如下所示:

      RESULTS:
      ------------------------------------------------------------
      CONNECTED
      
      (1 rows affected)
      

      如果您无法连接,请确保 DNS 正常运行,并且 AWS 和 Google Cloud 子网之间打开了防火墙规则。

  4. C:\SQLDataC:\SQLLog 中创建文件夹。数据库数据和日志文件使用这些文件夹。

    New-Item "C:\SQLData" –type directory
    New-Item "C:\SQLLog" –type directory
    
  5. C:\SQLBackup 处创建一个文件夹,并在 \\cluster-sql2\SQLBackup 中创建一个 Windows 共享,以便从 AWS 实例传输备份。您可以使用适用于这两个服务器的任何其他网络共享。

    New-Item "C:\SQLBackup" –type directory
    New-SmbShare -Name "SQLBackup" -Path "C:\SQLBackup" -FullAccess
    "dbeng.com\cluster-sql1$","dbeng.com\cluster-sql2$","NT
    SERVICE\MSSQLSERVER","authenticated users","dbeng.com\sql_service"
    

现已为可用性组创建了实例。由于您只有两个实例,在下一部分中,您将配置文件共享见证,提供尝试投票和仲裁。

创建文件共享见证

为了在故障切换情景中提供决定性投票权,实现仲裁,您需要创建一个充当见证者的文件共享。在本教程中,您将在网域控制器虚拟机上创建文件共享见证。在生产环境中,您可以在 Active Directory 网域内的任何服务器上创建文件共享见证。

  1. 使用 RDP 通过 dbeng\Administrator 连接到网域控制器虚拟机 dc-windows
  2. 打开提升权限的 PowerShell(以管理员身份运行)。
  3. 创建见证文件夹:

    New-Item "C:\QWitness" –type directory
    
  4. 共享该文件夹:

    New-SmbShare -Name "QWitness" -Path "C:\QWitness" -Description "SQL File Share Witness" -FullAccess "dbeng.com\Administrator", "dbeng.com\cluster-sql1$", "dbeng.com\cluster-sql2$"
    
  5. 使用 dbeng.com\Administrator 通过 RDP 连接到 cluster-sql1cluster-sql2

  6. 确认您可以通过这两个服务器访问共享目录:

    dir \\dc-windows\QWitness
    

    如果您无法访问共享目录,请尝试更改节点上的网络连接,以将 WINS 服务器设置为与网域服务器匹配。更改网络连接可能需要几秒钟的时间。以下屏幕截图显示了更新后的 WINS 设置:

    更新了高级 TCP/IP 设置中的 WINS 地址设置。

现在,可用性组已准备就绪。接下来,您需要配置故障切换集群。

配置故障切换集群

在本部分中,您将为两个实例配置 WSFC 并启用 Always On 高可用性。在 AWS 中,从该实例运行以下所有配置命令。

  1. 使用 RDP 连接到 AWS 实例(cluster-sql1)。
  2. 打开提升权限的 PowerShell(以管理员身份运行)。
  3. 设置反映您集群环境的变量。对于此示例,请设置以下变量:

    $node1 = "cluster-sql1.dbeng.com"
    $node2 = "cluster-sql2.dbeng.com"
    $nameWSFC = "cluster-dbclus" #Name of cluster
    $ipWSFC1 = "192.168.1.5" #IP address of cluster in subnet 1 (AWS)
    $ipWSFC2 = "10.1.1.5"    #IP address of cluster in subnet 2 (Google Cloud)
    
  4. 创建故障切换集群(运行此命令可能需要一些时间):

    New-Cluster -Name $nameWSFC -Node $node1, $node2 -NoStorage -StaticAddress $ipWSFC1, $ipWSFC2
    
    Set-ClusterQuorum -FileShareWitness \\dc-windows\QWitness
    
  5. 在节点 1 上启用 Always On 高可用性。如果您之前未启用 Always On,则这些命令会强制 SQL Server 重启。

    Enable-SqlAlwaysOn -ServerInstance $node1 -Force
    
  6. 在节点 2 上启用 Always On 高可用性。在启用 SQL Always On 之前,这些命令会停止 SQL Server 服务,因此,您可以忽略错误:Enable-SqlAlwaysOn : StopService failed for Service 'MSSQLSERVER'

    Get-Service -ComputerName $node2 -Name "MSSQLServer" | Stop-Service -Force
    
    Enable-SqlAlwaysOn -ServerInstance $node2 -Force
    
    Get-Service -ComputerName $node2 -Name "MSSQLServer" | Start-Service
    
  7. C:\SQLDataC:\SQLLog 中创建文件夹。将 TestDB 文件夹用于数据库数据和日志文件。如果您的服务器已有具有此文件夹结构的数据库,则可以跳过此步骤。如果不确定,请运行命令并忽略有关现有文件夹的所有错误消息。

    New-Item "C:\SQLData" –type directory
    New-Item "C:\SQLLog" –type directory
    

故障切换集群管理器已配置完毕。接下来,创建可用性组。

创建可用性组

在本部分中,您将在 AWS (cluster-sql1) 中创建测试数据库,并将其配置为使用新的可用性组。或者,您也可以为可用性组指定现有数据库。

  1. 使用 RDP 连接到 AWS 实例(cluster-sql1)。
  2. 打开提升权限的 PowerShell(以管理员身份运行)。
  3. C:\SQLBackup 中创建一个文件夹来存储数据库的备份。在新数据库上设置可用性组之前,需要备份。

    New-Item "C:\SQLBackup" –type directory
    
  4. 如果您尚未配置数据库,请运行 SQL Server Management Studio 并在 AWS 实例 (cluster-sql1) 中创建测试数据库:

    CREATE DATABASE TestDB
    ON PRIMARY (NAME = 'TestDB_Data', FILENAME='C:\SQLData\TestDB_Data.mdf', SIZE = 256MB, MAXSIZE = UNLIMITED, FILEGROWTH = 256MB )
    LOG ON (NAME = 'TestDB_Log', FILENAME='C:\SQLLog\TestDB_Log.ldf', SIZE = 256MB, MAXSIZE = UNLIMITED, FILEGROWTH = 256MB )
    GO
    
    USE [TestDB]
    Exec dbo.sp_changedbowner @loginame = 'sa', @map = false;
    ALTER DATABASE [TestDB] SET RECOVERY FULL;
    GO
    
    BACKUP DATABASE TestDB to disk = 'C:\SQLBackup\TestDB-backup.bak' WITH INIT
    GO
    
  5. 在 Microsoft SQL Server Management Studio 中,选择查询 > SQLCMD Mode

    SQL Server Management Studio 提供用于创建可用性组的向导。在本教程中,您将使用 SQL 命令,从而更轻松地调试在不同云提供商连接时可能遇到的问题。如果您愿意,可以运行可用性组向导并跳到后续步骤验证可用性组是否正在同步

  6. 在 SQLCMD 模式下运行以下查询。如果您使用的是现有数据库,请将 TestDB 替换为您的数据库名称。

    1. 在第一个节点中创建端点,并向端点授予权限:

      :Connect CLUSTER-SQL1
      IF NOT EXISTS (SELECT state FROM sys.endpoints WHERE name = N'Hadr_endpoint')
      BEGIN
        CREATE ENDPOINT [Hadr_endpoint]
        AS TCP (LISTENER_PORT = 5022)
        FOR DATA_MIRRORING (ROLE = WITNESS, ENCRYPTION = REQUIRED ALGORITHM AES)
      END
      GO
      
      IF (SELECT state FROM sys.endpoints WHERE name = N'Hadr_endpoint') <> 0
      BEGIN
        ALTER ENDPOINT [Hadr_endpoint] STATE = STARTED
      END
      GO
      
      use [master]
      GO
      
      IF SUSER_ID('DBENG\sql_service') IS NULL
        CREATE LOGIN [DBENG\sql_service] FROM WINDOWS
      GO
      
      GRANT CONNECT ON ENDPOINT::[Hadr_endpoint] TO [DBENG\sql_service]
      GO
      
    2. 在第一个节点中启用 AlwaysOn_health 扩展事件会话。可用性组需要扩展事件会话。

      :Connect CLUSTER-SQL1
      IF EXISTS(SELECT * FROM sys.server_event_sessions WHERE name='AlwaysOn_health')
      BEGIN
        ALTER EVENT SESSION [AlwaysOn_health] ON SERVER WITH (STARTUP_STATE=ON);
      END
      IF NOT EXISTS(SELECT * FROM sys.dm_xe_sessions WHERE name='AlwaysOn_health')
      BEGIN
        ALTER EVENT SESSION [AlwaysOn_health] ON SERVER STATE=START;
      END
      GO
      
    3. 在第二个节点中创建端点,并向端点授予权限:

      :Connect CLUSTER-SQL2
      IF NOT EXISTS (SELECT state FROM sys.endpoints WHERE name = N'Hadr_endpoint')
      BEGIN
        CREATE ENDPOINT [Hadr_endpoint]
          AS TCP (LISTENER_PORT = 5022)
          FOR DATA_MIRRORING (ROLE = WITNESS, ENCRYPTION = REQUIRED ALGORITHM AES)
      END
      GO
      
      IF (SELECT state FROM sys.endpoints WHERE name = N'Hadr_endpoint') <> 0
      BEGIN
        ALTER ENDPOINT [Hadr_endpoint] STATE = STARTED
      END
      GO
      
      use [master]
      GO
      
      IF SUSER_ID('DBENG\sql_service') IS NULL
        CREATE LOGIN [DBENG\sql_service] FROM WINDOWS
      GO
      
      GRANT CONNECT ON ENDPOINT::[Hadr_endpoint] TO [DBENG\sql_service]
      GO
      
    4. 在第二个节点中启用 AlwaysOn_health 扩展事件会话。可用性组需要扩展事件会话。

      :Connect CLUSTER-SQL2
      IF EXISTS(SELECT * FROM sys.server_event_sessions WHERE name='AlwaysOn_health')
      BEGIN
        ALTER EVENT SESSION [AlwaysOn_health] ON SERVER WITH (STARTUP_STATE=ON);
      END
      IF NOT EXISTS(SELECT * FROM sys.dm_xe_sessions WHERE name='AlwaysOn_health')
      BEGIN
        ALTER EVENT SESSION [AlwaysOn_health] ON SERVER STATE=START;
      END
      GO
      
    5. 在第一个节点中创建可用性组:

      :Connect CLUSTER-SQL1
      USE [master]
      GO
      
      --DROP AVAILABILITY GROUP [cluster-ag];
      GO
      
      CREATE AVAILABILITY GROUP [cluster-ag]
      WITH (AUTOMATED_BACKUP_PREFERENCE = SECONDARY,
      DB_FAILOVER = OFF,
      DTC_SUPPORT = NONE)
      FOR DATABASE [TestDB]
      REPLICA ON N'CLUSTER-SQL1' WITH (ENDPOINT_URL = N'TCP://CLUSTER-SQL1.dbeng.com:5022', FAILOVER_MODE = MANUAL, AVAILABILITY_MODE = ASYNCHRONOUS_COMMIT, BACKUP_PRIORITY = 50, SEEDING_MODE = MANUAL),
        N'CLUSTER-SQL2' WITH (ENDPOINT_URL = N'TCP://cluster-sql2.dbeng.com:5022', FAILOVER_MODE = MANUAL, AVAILABILITY_MODE = ASYNCHRONOUS_COMMIT, BACKUP_PRIORITY = 50, SEEDING_MODE = MANUAL);
      GO
      
    6. 将第二个节点加入新创建的可用性组:

      :Connect CLUSTER-SQL2
      ALTER AVAILABILITY GROUP [cluster-ag] JOIN;
      GO
      
    7. 在第一个节点中创建数据库备份:

      :Connect CLUSTER-SQL1
      BACKUP DATABASE [TestDB] TO DISK = N'\\CLUSTER-SQL2\SQLBackup\TestDB.bak' WITH COPY_ONLY, FORMAT, INIT, SKIP, REWIND, NOUNLOAD, COMPRESSION, STATS = 5
      GO
      
    8. 在第二个节点上恢复数据库备份:

      :Connect CLUSTER-SQL2
      RESTORE DATABASE [TestDB] FROM DISK = N'\\CLUSTER-SQL2\SQLBackup\TestDB.bak' WITH NORECOVERY, NOUNLOAD, STATS = 5
      GO
      
    9. 在第一个节点中创建事务日志备份:

      :Connect CLUSTER-SQL1
      BACKUP LOG [TestDB] TO DISK = N'\\CLUSTER-SQL2\SQLBackup\TestDB.trn' WITH NOFORMAT, INIT, NOSKIP, REWIND, NOUNLOAD, COMPRESSION, STATS = 5
      GO
      
    10. 在第二个节点中恢复事务日志备份:

      :Connect CLUSTER-SQL2
      RESTORE LOG [TestDB] FROM  DISK = N'\\CLUSTER-SQL2\SQLBackup\TestDB.trn' WITH NORECOVERY, NOUNLOAD, STATS = 5
      GO
      
  7. 为了确保同步中没有错误,请运行以下查询并确保列 connected_state_desc 的值为 CONNECTED

    :Connect CLUSTER-SQL2
    select r.replica_server_name, r.endpoint_url,
           rs.connected_state_desc, rs.last_connect_error_description,
           rs.last_connect_error_number, rs.last_connect_error_timestamp
     from sys.dm_hadr_availability_replica_states rs
      join sys.availability_replicas r
       on rs.replica_id=r.replica_id
     where rs.is_local=1
    
    • 如果 connected_state_desc 列包含错误消息 An error occurred while receiving data: '24(The program issued a command but the command length is incorrect)',请运行以下命令以尝试清除错误:

      :Connect CLUSTER-SQL1
      IF SUSER_ID('DBENG\CLUSTER-SQL2$') IS NULL
         CREATE LOGIN [DBENG\CLUSTER-SQL2$] FROM WINDOWS
      GO
      
      GRANT CONNECT ON ENDPOINT::[Hadr_endpoint] TO [DBENG\CLUSTER-SQL2$]
      GO
      
      :Connect CLUSTER-SQL2
      IF SUSER_ID('DBENG\CLUSTER-SQL1$') IS NULL
        CREATE LOGIN [DBENG\CLUSTER-SQL1$] FROM WINDOWS
      GO
      
      GRANT CONNECT ON ENDPOINT::[Hadr_endpoint] TO [DBENG\CLUSTER-SQL1$]
      GO
      

      重新运行上一个查询以确保不再发生同步错误。您可能需要等待几分钟,以便清除错误。如果错误仍然存在,请参阅对 Always On 可用性组配置 (SQL Server) 进行问题排查

  8. 完成可用性组设置:

    :Connect CLUSTER-SQL2
    ALTER DATABASE [TestDB] SET HADR AVAILABILITY GROUP = [cluster-ag]
    GO
    
    ALTER DATABASE [TestDB] SET HADR RESUME;
    GO
    
  9. 验证可用性组是否正在同步:

    1. 在 SQL Server Management Studio 的 Always On 高可用性 > 可用性组下,右键点击可用性组,然后选择显示信息中心

    2. 验证主同步状态是否为已同步,辅助同步状态为同步,如以下屏幕截图所示:

      SQL Server Management Studio 显示可用性组的同步状态。

  10. 要添加监听器,请在 Always On 高可用性 > 可用性组 > cluster-ag (Primary) > 可用性组监听器下,右键点击可用性组名称,然后选择添加监听器

  11. 新建可用性组监听器对话框中,指定监听器的以下参数:

    • 监听器 DNS 名称ag-listener
    • 端口1433
    • 网络模式Static IP
  12. 添加两个子网和 IP 地址字段。对于此示例,使用以下子网和 IP 地址对。这些对是除了您在 SQL 服务实例虚拟机上的主要 IP 地址以外创建的 IP 地址:

    1. 对于第一个键值对,请输入以下值:
      • 子网192.168.1.0/24
      • IPv4 地址192.168.1.6
    2. 对于第二对,请输入以下值:
      • 子网10.1.1.0/24
      • IPv4 地址10.1.1.6
  13. 添加子网和 IP 地址对后,点击确定

  14. 使用 ag-listener.dbeng.com 作为 SQL Server 数据库名称(而不是实例名称)连接到 SQL Server。此连接指向当前活跃的实例。

    1. Object Explorer 中,点击连接,然后选择数据库引擎
    2. 连接到服务器对话框的服务器名称字段中,输入监听器 ag-listener.dbeng.com
    3. 添加服务器名称后,点击连接Object Explorer 会显示新的连接,如以下屏幕截图所示:

      Object Explorer 会显示连接。

    如果您使用 RDP 连接到 cluster-sql2,则可以选择重复执行此步骤以建立连接。

添加测试数据

在本部分中,您将向 cluster-sql1 中的 TestDB 数据库添加一个测试表和一些测试数据,然后验证数据复制。

  1. cluster-sql1 中创建名为 Persons 的表:

    :Connect CLUSTER-SQL1
    USE TestDB;
    CREATE TABLE Persons (
        PersonID int,
        LastName varchar(255),
        FirstName varchar(255),
        PRIMARY KEY (PersonID)
    );
    
  2. 插入几行:

    :Connect CLUSTER-SQL1
    USE TestDB;
    INSERT INTO Persons (PersonId, LastName, FirstName)
      VALUES (1, 'Velasquez', 'Ava');
    INSERT INTO Persons (PersonId, LastName, FirstName)
      VALUES (2, 'Delaxcrux', 'Paige');
    
  3. 如果您使用的是企业版,请启用读取副本的读取访问权限 (cluster-sql2),以便验证是否进行了复制。标准版不支持对只读副本的只读权限。如果您使用的是标准版,请跳到下一部分执行切换至 Google Cloud 部分。

    :Connect CLUSTER-SQL1
    ALTER AVAILABILITY GROUP [cluster-ag]
    MODIFY REPLICA ON N'CLUSTER-SQL2' WITH (SECONDARY_ROLE(ALLOW_CONNECTIONS = ALL))
    GO
    
  4. 在企业版中,查询 cluster-sql2 中的表以验证表内容是否已复制:

    :Connect CLUSTER-SQL2
    SELECT * FROM TestDB.dbo.Persons;
    

现在,数据已从 cluster-sql1 复制到 cluster-sql2,而由您执行切换。如果您只想执行复制,则可以跳过以下部分,而不执行切换或回退操作。如果您不想保留用于执行复制的资源,则可以按照本教程末尾的清理步骤来避免产生费用。

执行到 Google Cloud 的切换

为了确保数据集具有一致性,必须停止向 cluster-sql1 写入数据的客户端,以便在执行切换之前将所有数据复制到 cluster-sql2

为确保一致性,必须完整复制所有数据。在本部分中,您将可用性模式更改为 SYNCHRONOUS_COMMIT 以完成数据复制。此更改可确保将 cluster-sql1 的完整复制到 cluster-sql2

  1. 如需将两个节点的可用性模式更改为同步提交,请在 cluster-sql1 中运行以下 SQL 命令。确保两个节点均设为同步提交是确保不会丢失任何数据的唯一方法。

    :Connect CLUSTER-SQL1
    ALTER AVAILABILITY GROUP [cluster-ag]
    MODIFY REPLICA ON N'CLUSTER-SQL1' WITH (AVAILABILITY_MODE = SYNCHRONOUS_COMMIT)
    GO
    
    ALTER AVAILABILITY GROUP [cluster-ag]
    MODIFY REPLICA ON N'CLUSTER-SQL2' WITH (AVAILABILITY_MODE = SYNCHRONOUS_COMMIT)
    GO
    
  2. 现在可以将 Cluster-sql2 设置为主节点了。连接到 cluster-sql2 并将其设置为主节点:

    :Connect CLUSTER-SQL2
    ALTER AVAILABILITY GROUP [cluster-ag] FAILOVER;
    GO
    
  3. 在两个节点中将可用性模式更改为异步提交。由于 cluster-sql2 是主节点,因此请在 cluster-sql2 中运行以下 SQL 命令:

    :Connect CLUSTER-SQL2
    ALTER AVAILABILITY GROUP [cluster-ag]
    MODIFY REPLICA ON N'CLUSTER-SQL1' WITH (AVAILABILITY_MODE = ASYNCHRONOUS_COMMIT)
    GO
    
    ALTER AVAILABILITY GROUP [cluster-ag]
    MODIFY REPLICA ON N'CLUSTER-SQL2' WITH (AVAILABILITY_MODE = ASYNCHRONOUS_COMMIT)
    GO
    

    现在,您可以使用 cluster-sql2 作为应用的主节点了。cluster-sql1 是异步复制的辅助实例。

  4. 现在,cluster-sql2 是主节点,查询 cluster-sql2 中的表以验证表内容是否已复制:

    :Connect CLUSTER-SQL2
    SELECT * FROM TestDB.dbo.Persons;
    

    输出与您在本教程前面表中插入的测试数据相匹配。

如需执行进一步的复制验证,您可以创建一个新表并在新主实例上插入一行。当表及其行显示在二级时,您就知道复制正在进行。

后备操作

有时,您可能需要从新的主实例恢复到原始主实例。在本教程中,当您提前完成切换到 Google Cloud,您已将之前二级主实例 (cluster-sql1 ) 指向新的主实例(cluster-sql2)。

要完成回退过程,请按照执行切换到 Google Cloud 过程操作,并替换以下值:

  • 将原始主实例 (cluster-sql1) 替换为新的主实例 (cluster-sql2)。
  • 将原始次要地址 (cluster-sql2) 替换为新的次要地址 (cluster-sql1)。

清理

为避免因本教程中使用的资源导致您的 Google Cloud 账号产生费用,请删除包含这些资源的项目,或者保留项目但删除各个资源。

为避免因本教程中使用的资源导致您的 Google Cloud 账号产生费用,请执行以下操作:

删除 Google Cloud 中的项目

  1. 在 Google Cloud 控制台中,进入管理资源页面。

    转到“管理资源”

  2. 在项目列表中,选择要删除的项目,然后点击删除
  3. 在对话框中输入项目 ID,然后点击关闭以删除项目。

删除 AWS 中的项目

由于您在 AWS 中创建和使用资源,因此这些资源将继续产生费用。为避免进一步增加费用,请在 AWS 上删除这些资源。

后续步骤