使用快照复制功能将数据从 SQL Server 2017 迁移到 Cloud SQL for SQL Server


本教程介绍了如何将数据从在 Compute Engine 上运行的 Microsoft SQL Server 2017 Enterprise 迁移到 Cloud SQL for SQL Server 2017 Enterprise。如果您是系统管理员、开发者、工程师、数据库管理员或 DevOps 工程师,那么本教程非常适合您。本教程介绍如何设置 SQL Server Distributor,如何使用 SQL Server Agent 将快照复制到 Cloud SQL for SQL Server 2017 并验证数据已成功导入。

在本教程中,您将使用快照复制让源和目标保持同步。快照复制会向订阅者发送每篇文章(即已发布的数据库对象)的完整副本。Cloud SQL 还支持仅发送增量数据的事务副本。事务副本的限制是表必须具有主键。如需详细了解 SQL Server 副本类型,请参阅 SQL Server 文档

为简单起见,本教程使用源 SQL Server 托管 Distributor。在生产场景中,如果从 Google Cloud 外部复制数据,您可能更倾向于将 Distributor 托管在 Compute Engine 实例上的 Google Cloud 端。

本教程假定您熟悉以下内容:

目标

  • 在 Compute Engine 上创建 SQL Server 虚拟机实例以托管示例数据库。
  • 填充示例数据库。
  • 创建 Cloud SQL for SQL Server 实例。
  • 创建 Distributor。
  • 设置发布和订阅。
  • 启动从 SQL Server 复制到 Cloud SQL。
  • 验证导入的数据。

费用

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

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

准备工作

  1. 登录您的 Google Cloud 账号。如果您是 Google Cloud 新手,请创建一个账号来评估我们的产品在实际场景中的表现。新客户还可获享 $300 赠金,用于运行、测试和部署工作负载。
  2. 在 Google Cloud Console 中的项目选择器页面上,选择或创建一个 Google Cloud 项目

    转到“项目选择器”

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

  4. 启用 Cloud SQL Admin and Compute Engine API API。

    启用 API

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

    转到“项目选择器”

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

  7. 启用 Cloud SQL Admin and Compute Engine API API。

    启用 API

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

    激活 Cloud Shell

    Cloud Shell 会话随即会在 Google Cloud 控制台的底部启动,并显示命令行提示符。Cloud Shell 是一个已安装 Google Cloud CLI 且已为当前项目设置值的 Shell 环境。该会话可能需要几秒钟时间来完成初始化。

  9. 安装您选择的任何远程桌面协议 (RDP) 客户端。如需了解详情,请参阅 Microsoft 远程桌面客户端。如果您已安装 RDP 客户端,则可以跳过此任务。

完成本文档中描述的任务后,您可以通过删除所创建的资源来避免继续计费。如需了解详情,请参阅清理

创建 SQL Server 虚拟机

第一步是在 Compute Engine 上的 Windows 2016 虚拟机上创建一个 SQL Server 2017 实例,并使用 RDP 连接到该实例。

  1. 在 Cloud Shell 中,在 Windows Server 2016 上创建 SQL Server 2017 Standard 版实例。源数据库必须是 SQL Server Standard 版或 Enterprise 版数据库,因为较低层级没有数据库发布者功能。

    gcloud compute instances create sqlserver --machine-type=n1-standard-4 \
        --boot-disk-size=100GB \
        --image-project=windows-sql-cloud \
        --image-family=sql-std-2017-win-2016 \
        --zone=us-central1-f  \
        --scopes=https://www.googleapis.com/auth/cloud-platform
    

    在本教程中,您将在 us-central1-f 区域创建启动磁盘大小为 100 GB 的实例。如需了解详情,请参阅 Cloud 位置

  2. 生成 Windows 密码:

    gcloud compute reset-windows-password sqlserver --zone=us-central1-f
    
  3. 在 Google Cloud Console 中,转到虚拟机实例页面。

    打开“虚拟机实例”

  4. 在 Google Cloud 控制台的 Compute Engine 部分中,点击 RDP 下拉列表,然后选择下载 RDP 文件选项以下载实例的 RDP 文件。

    使用此文件通过 RDP 客户端连接到实例。如需了解详情,请参阅 Microsoft 远程桌面客户端

  5. 用户名密码字段中,输入您为 SQL Server 虚拟机实例创建的用户名和密码。将网域字段留空,然后点击确定以连接到 SQL Server 虚拟机。

    用于输入用户名和密码的对话框的屏幕截图。

    出现提示时,接受证书。

  6. 如果您接受条款,请点击继续

  7. 在实例中,将所有窗口最小化,在 Windows 任务栏上点击开始,输入 PowerShell,然后右键点击 Windows PowerShell 应用,并选择以管理员身份运行

  8. 在 PowerShell 提示符下,创建一个目录结构来存储此数据库:

    mkdir c:\sql-server-data\adventureworks
    

创建和填充示例数据库

现在,您可以下载 Microsoft 的 AdventureWorks 数据库备份文件,并将其恢复到 SQL Server 实例中。此数据库模拟您要迁移的生产数据库。

  1. 从 PowerShell 命令行将 AdventureWorksLT2017.bak 备份文件下载到 C 盘:

    bitsadmin /transfer sampledb /dynamic /download /priority FOREGROUND "https://github.com/Microsoft/sql-server-samples/releases/download/adventureworks/AdventureWorksLT2017.bak " C:\sql-server-data\AdventureWorksLT2017.bak
    
  2. 恢复数据库:

    osql -E -Q "USE [master]
    RESTORE DATABASE [AdventureWorksLT2017]
    FROM  DISK = N'C:\sql-server-data\AdventureWorksLT2017.bak' WITH  FILE = 1,
    MOVE N'AdventureWorksLT2012_Data' TO N'C:\sql-server-data\adventureworks\AdventureWorksLT2012.mdf',
    MOVE N'AdventureWorksLT2012_Log' TO N'C:\sql-server-data\adventureworks\AdventureWorksLT2012_log.ldf',
    NOUNLOAD,  STATS = 5"
    
  3. 通过查询 Customer 表中的行数来验证新恢复的数据库。输出为 847 行。

    osql -E -Q "select count(*) from AdventureWorksLT2017.SalesLT.Customer"
    

准备 Cloud SQL 实例

  1. 在 Cloud Shell 中,创建 Cloud SQL for SQL Server 2017 Enterprise 版实例:

    gcloud sql instances create target-sqlserver  \
        --database-version=SQLSERVER_2017_STANDARD \
        --cpu=4 \
        --memory=15 \
        --storage-size=100 \
        --root-password=sqlserver12@ \
        --zone=us-central1-f
    

    root 用户是 sqlserver,其密码是 sqlserver12@。另请记下 SQL Server IP 地址。

  2. 将源 SQL Server 虚拟机的 IP 地址存储在环境变量中:

    sql_source_ip=$(gcloud compute instances describe sqlserver \
        --zone=us-central1-f | grep natIP | awk '{print $2}')
    echo $sql_source_ip
    
  3. 将包含 Cloud SQL 实例的 SQL Server 虚拟机 IP 地址添加到许可名单(白名单):

    gcloud sql instances patch target-sqlserver --authorized-networks=$sql_source_ip
    
  4. 创建目标数据库:

    gcloud sql databases create AdventureWorksTarget --instance=target-sqlserver
    
  5. 在以管理员身份启动的 PowerShell 命令行中,检查与 Cloud SQL for SQL Server 的连接:

    $cloud_sql_server_ip=gcloud sql instances describe target-sqlserver --format='value(ipAddresses.ipAddress)'
    osql -S $cloud_sql_server_ip -U sqlserver -P sqlserver12@ -Q "select 'test'"
    

    该命令会输出 'test'

启动从虚拟机到 Cloud SQL 的复制

通过使用 SQL Server 快照复制,创建一个作业,以将数据库快照复制到 Cloud SQL 中。

设置 Distributor

现在,您将 SQL Server 虚拟机配置为 SQL Server Distributor。在实际应用中,Distributor 可以在单独的机器上运行,但在本教程中,在同一个虚拟机上运行它。

  1. 从以管理员身份启动的 PowerShell 命令行中,更新 SQL Server 本地实例名称以与虚拟机主机名相匹配:

    $servername=hostname
    osql -E -Q "sp_dropserver 'INST-INSTALL-SQ';"
    osql -E -Q "sp_addserver '$servername', local;"
    Restart-Service -F MSSQLServer
    mkdir c:\sql-server-data\repldata
    

    如果您收到 Cannot open MSSQLServer service on computer '.'. 错误,可能是您没有以管理员身份运行 PowerShell 命令行。

  2. 验证实例名称现在是否为 "sqlserver"

    osql -E -Q "select @@servername;"
    
  3. 指定分发数据库:

    $servername=hostname
    osql -E -Q "use master; exec sp_adddistributor @distributor = N'$servername', @password = N'';"
    osql -E -Q "exec sp_adddistributiondb @database = N'distribution', @data_folder = N'C:\Program Files\Microsoft SQL Server\MSSQL14.MSSQLSERVER\MSSQL\Data', @log_folder = N'C:\Program Files\Microsoft SQL Server\MSSQL14.MSSQLSERVER\MSSQL\Data', @log_file_size = 2, @min_distretention = 0, @max_distretention = 72, @history_retention = 48, @deletebatchsize_xact = 5000, @deletebatchsize_cmd = 2000, @security_mode = 1"
    
  4. 配置分发数据库:

    osql -E -Q "
    use [distribution]
    if (not exists (select * from sysobjects where name = 'UIProperties' and type = 'U '))
        create table UIProperties(id int)
    if (exists (select * from ::fn_listextendedproperty('SnapshotFolder', 'user', 'dbo', 'table', 'UIProperties', null, null)))
        exec sp_updateextendedproperty N'SnapshotFolder', N'c:\sql-server-data\repldata', 'user', dbo, 'table', 'UIProperties'
    else
        exec sp_addextendedproperty N'SnapshotFolder', N'c:\sql-server-data\repldata', 'user', dbo, 'table', 'UIProperties'
    "
    
  5. 将 SQL Server 虚拟机与 Distributor 注册为发布者:

    osql -E -Q "exec sp_adddistpublisher @publisher = N'$servername',
    @distribution_db = N'distribution', @security_mode = 1, @working_directory
    = N'c:\sql-server-data\repldata', @trusted = N'false', @thirdparty_flag =
    0, @publisher_type = N'MSSQLSERVER'"
    

设置发布

分发现已设置完毕,您可以配置要发布哪些表了。

  1. 在 PowerShell 命令行中,启用并启动 SQL Server Agent:

    Set-Service -Name SQLServerAgent -StartupType Automatic
    Start-Service -Name SQLServerAgent
    
  2. AdventureWorksLT2017 数据库创建发布:

    $servername=hostname
    osql -E -Q "
    use [AdventureWorksLT2017]
    exec sp_replicationdboption @dbname = N'AdventureWorksLT2017', @optname = N'publish', @value = N'true'"
    
    osql -E -Q "use [AdventureWorksLT2017]
    exec sp_addpublication @publication = N'advn-pub3', @description = N'Snapshot publication of database ''AdventureWorksLT2017'' from Publisher ''$servername''.', @sync_method = N'native', @retention = 0, @allow_push = N'true', @allow_pull = N'true', @allow_anonymous = N'true', @enabled_for_internet = N'false', @snapshot_in_defaultfolder = N'true', @compress_snapshot = N'false', @ftp_port = 21, @ftp_login = N'anonymous', @allow_subscription_copy = N'false', @add_to_active_directory = N'false', @repl_freq = N'snapshot', @status = N'active', @independent_agent = N'true', @immediate_sync = N'true', @allow_sync_tran = N'false', @autogen_sync_procs = N'false', @allow_queued_tran = N'false', @allow_dts = N'false', @replicate_ddl = 1"
    
  3. 配置发布,以将源的快照发送到 Cloud SQL,每小时发送一次:

    osql -E -Q "
    use [AdventureWorksLT2017]
    exec sp_addpublication_snapshot @publication = N'advn-pub3', @frequency_type = 4, @frequency_interval = 1, @frequency_relative_interval = 1, @frequency_recurrence_factor = 0, @frequency_subday = 8, @frequency_subday_interval = 1, @active_start_time_of_day = 0, @active_end_time_of_day = 235959, @active_start_date = 0, @active_end_date = 0, @job_login = null, @job_password = null, @publisher_security_mode = 1"
    
  4. 将文章(表)添加到发布。虽然 AdventureWorksLT2017 数据库包含许多表,但为了简单起见,您只复制三个表:AddressCustomerCustomerAddress

    osql -E -Q "
    use [AdventureWorksLT2017]
    exec sp_addarticle @publication = N'advn-pub3', @article = N'Address', @source_owner = N'SalesLT', @source_object = N'Address', @type = N'logbased', @description = null, @creation_script = null, @pre_creation_cmd = N'drop', @schema_option = 0x000000000803509D, @identityrangemanagementoption = N'manual', @destination_table = N'Address', @destination_owner = N'SalesLT', @vertical_partition = N'false'
    "
    
    osql -E -Q "
    use [AdventureWorksLT2017]
    exec sp_addarticle @publication = N'advn-pub3', @article = N'Customer', @source_owner = N'SalesLT', @source_object = N'Customer', @type = N'logbased', @description = null, @creation_script = null, @pre_creation_cmd = N'drop', @schema_option = 0x000000000803509D, @identityrangemanagementoption = N'manual', @destination_table = N'Customer', @destination_owner = N'SalesLT', @vertical_partition = N'false'
    "
    
    osql -E -Q "
    use [AdventureWorksLT2017]
    exec sp_addarticle @publication = N'advn-pub3', @article = N'CustomerAddress', @source_owner = N'SalesLT', @source_object = N'CustomerAddress', @type = N'logbased', @description = null, @creation_script = null, @pre_creation_cmd = N'drop', @schema_option = 0x000000000803509D, @identityrangemanagementoption = N'manual', @destination_table = N'CustomerAddress', @destination_owner = N'SalesLT', @vertical_partition = N'false'
    "
    
  5. 手动创建文章的快照。如果您不这样做,则调度程序创建初始快照可能需要长达一小时的时间。

    osql -E -Q "use [AdventureWorksLT2017]
    exec sp_startpublication_snapshot @publication = N'advn-pub3'"
    

设置订阅

现在,您可以创建订阅以将已发布数据发送到 Cloud SQL。

  1. 从 PowerShell 命令行中,创建订阅以将发布快照发送到 Cloud SQL:

    $cloud_sql_server_ip=gcloud sql instances describe target-sqlserver --format='value(ipAddresses.ipAddress)'
    $cloud_sql_user="sqlserver"
    $cloud_sql_password="sqlserver12@"
    $target_db_name="AdventureWorksTarget"
    osql -E -Q " use [AdventureWorksLT2017] exec sp_addsubscription @publication = N'advn-pub3', @subscriber = N'$cloud_sql_server_ip', @destination_db = N'$target_db_name', @subscription_type = N'Push', @sync_type = N'automatic', @article = N'all', @update_mode = N'read only', @subscriber_type = 0
    
    exec sp_addpushsubscription_agent @publication = N'advn-pub3', @subscriber = N'$cloud_sql_server_ip', @subscriber_db = N'$target_db_name', @job_login = null, @job_password = null, @subscriber_security_mode = 0, @subscriber_login = N'$cloud_sql_user', @subscriber_password = N'$cloud_sql_password', @frequency_type = 64, @frequency_interval = 0, @frequency_relative_interval = 0, @frequency_recurrence_factor = 0, @frequency_subday = 0, @frequency_subday_interval = 0, @active_start_time_of_day = 0, @active_end_time_of_day = 235959, @active_start_date = 20200408, @active_end_date = 99991231, @enabled_for_syncmgr = N'False', @dts_package_location = N'Distributor' "
    
  1. 验证 Cloud SQL 实例中是否有该数据:

    osql -S $cloud_sql_server_ip -U $cloud_sql_user -P $cloud_sql_password -Q "select count(*) from [AdventureWorksTarget].[SalesLT].[CustomerAddress] UNION
    select count(*) from [AdventureWorksTarget].[SalesLT].[Customer]
    UNION
    Select count(*) from [AdventureWorksTarget].[SalesLT].[Address]"
    

    该命令会输出 417450847

清除数据

完成本教程后,您可以清理您创建的资源,让它们停止使用配额,以免产生费用。以下部分介绍如何删除或关闭这些资源。

删除项目

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

    转到“管理资源”

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

后续步骤