擷取資料變更,以便從SQL伺服器進行複寫 - AWS 資料庫遷移服務

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

擷取資料變更,以便從SQL伺服器進行複寫

本主題說明如何在SQL伺服器來源上設定CDC複製。

在現場部署或 Amazon 上擷取自我管理SQL伺服器的資料變更 EC2

若要從來源 Microsoft SQL 伺服器資料庫擷取變更,請確定資料庫已設定為完整備份。在完整復原模式或大量記錄模式下設定資料庫。

對於自我管理的SQL伺服器來源,請 AWS DMS 使用下列項目:

MS-Replication

針對具有主索引鍵的資料表擷取變更。您可以將系統管理員權限授與來源SQL伺服器執行個體上的 AWS DMS 端點使用者,以自動設定此設定。或者,您可以按照本節中的步驟準備來源,並使用沒有端點系統管理員權限的 AWS DMS 使用者。

女士-CDC

針對不具有主索引鍵的資料表擷取變更。CDC在數據庫級別和所有表單獨啟用 MS-。

為進行中的複寫設定SQL伺服器資料庫時 (CDC),您可以執行下列其中一項作業:

  • 使用 sysadmin 角色設定進行中複寫。

  • 設定進行中複寫不使用 sysadmin 角色。

在自我管SQL理的伺服器上設定進行中的複寫

本節包含在具有或不使用 sysadmin 角色的自我管理SQL伺服器上設定持續複寫的相關資訊。

在自我管理的SQL伺服器上設定持續複寫:使用系統管理員角色

AWS DMS SQL伺服器的持續複寫會針對具有主索引鍵的資料表使用原生SQL伺服器複寫,並針對沒有主索引鍵的資料表變更資料擷取 (CDC)。

在設定進行中複寫之前,請參閱從SQL伺服器來源使用進行中複寫 (CDC) 的先決條件

對於具有主索引鍵的表格,通常 AWS DMS 可以在來源上設定所需的人工因素。不過,對於自我管理的SQL伺服器來源執行個體,請務必先手動設定SQL伺服器發佈。執行此操作之後,具有 sysadmin 權限的 AWS DMS 來源使用者可以自動為具有主索引鍵的資料表建立發行集。

若要檢查是否已設定分發,請執行下列命令。

sp_get_distributor

如果資料欄分佈的結果是 NULL,則表示尚未設定分佈。您可以使用下列程序設定分佈。

設定分佈
  1. 使用SQL伺服器管理 Studio (SSMS) 工具 Connect 到SQL伺服器來源資料庫。

  2. 開啟複寫資料夾的內容 (按一下滑鼠右鍵) 選單,然後選擇設定分佈。[設定分佈精靈] 隨即顯示。

  3. 按照精靈的指示輸入預設值,然後建立分佈。

設定 CDC

AWS DMS 版本 3.4.7 及更高版本可以CDC為您的數據庫和所有表自動設置 MS,如果您不使用只讀複本。若要使用此功能,請SetUpMsCdcForTablesECA將設定為 true。如需有關的資訊ECAs,請參閱端點設定

對於 3.4.7 之 AWS DMS 前的版本或作為來源的唯讀複本,請執行下列步驟:

  1. 對於沒有主鍵的表,CDC為數據庫設置 MS-。若要這麼做,請使用已指派 sysadmin 角色的帳戶,並執行下列命令。

    use [DBname] EXEC sys.sp_cdc_enable_db
  2. 接下來,CDC為每個源表設置 MS-。對於每個具有唯一鍵但沒有主鍵的表,運行以下查詢來設置 MS-CDC。

    exec sys.sp_cdc_enable_table @source_schema = N'schema_name', @source_name = N'table_name', @index_name = N'unique_index_name', @role_name = NULL, @supports_net_changes = 1 GO
  3. 對於沒有主鍵或沒有唯一鍵的每個表,運行以下查詢來設置 MS-CDC。

    exec sys.sp_cdc_enable_table @source_schema = N'schema_name', @source_name = N'table_name', @role_name = NULL GO

如需有關針對特定資料表設定 MS-的CDC詳細資訊,請參閱SQL伺服器文件

在獨立SQL伺服器上設定持續複寫:沒有系統管理員角色

本節說明如何為不需要使用者帳戶擁有系統管理員權限的獨立SQL伺服器資料庫來源設定進行中複寫。

注意

執行本節中的步驟後,非系統管理員DMS使用者將擁有執行下列作業的權限:

  • 從線上交易記錄檔讀取變更

  • 從交易記錄備份檔讀取變更的磁碟存取權

  • 添加或更改使DMS用的出版物

  • 將文章新增至出版物

  1. 如中所述,設定用於複製的 Microsoft SQL 伺服器擷取資料變更,以便從SQL伺服器進行複寫

  2. 在來源資料庫REPLICATION上啟用 MS-。此操作可以手動完成,也可以透過以 sysadmin 使用者身分執行任務一次來完成。

  3. 使用下列指令碼在來源資料庫上建立 awsdms 結構描述:

    use master go create schema awsdms go -- Create the table valued function [awsdms].[split_partition_list] on the Master database, as follows: USE [master] GO set ansi_nulls on go set quoted_identifier on go if (object_id('[awsdms].[split_partition_list]','TF')) is not null drop function [awsdms].[split_partition_list]; go create function [awsdms].[split_partition_list] ( @plist varchar(8000), —A delimited list of partitions @dlm nvarchar(1) —Delimiting character ) returns @partitionsTable table —Table holding the BIGINT values of the string fragments ( pid bigint primary key ) as begin declare @partition_id bigint; declare @dlm_pos integer; declare @dlm_len integer; set @dlm_len = len(@dlm); while (charindex(@dlm,@plist)>0) begin set @dlm_pos = charindex(@dlm,@plist); set @partition_id = cast( ltrim(rtrim(substring(@plist,1,@dlm_pos-1))) as bigint); insert into @partitionsTable (pid) values (@partition_id) set @plist = substring(@plist,@dlm_pos+@dlm_len,len(@plist)); end set @partition_id = cast (ltrim(rtrim(@plist)) as bigint); insert into @partitionsTable (pid) values ( @partition_id ); return end GO
  4. 使用下列指令碼在 Master 資料庫上建立 [awsdms].[rtm_dump_dblog] 程序:

    use [MASTER] go if (object_id('[awsdms].[rtm_dump_dblog]','P')) is not null drop procedure [awsdms].[rtm_dump_dblog]; go set ansi_nulls on go set quoted_identifier on GO CREATE procedure [awsdms].[rtm_dump_dblog] ( @start_lsn varchar(32), @seqno integer, @filename varchar(260), @partition_list varchar(8000), — A comma delimited list: P1,P2,... Pn @programmed_filtering integer, @minPartition bigint, @maxPartition bigint ) as begin declare @start_lsn_cmp varchar(32); — Stands against the GT comparator SET NOCOUNT ON — – Disable "rows affected display" set @start_lsn_cmp = @start_lsn; if (@start_lsn_cmp) is null set @start_lsn_cmp = '00000000:00000000:0000'; if (@partition_list is null) begin RAISERROR ('Null partition list waspassed',16,1); return end if (@start_lsn) is not null set @start_lsn = '0x'+@start_lsn; if (@programmed_filtering=0) SELECT [Current LSN], [operation], [Context], [Transaction ID], [Transaction Name], [Begin Time], [End Time], [Flag Bits], [PartitionID], [Page ID], [Slot ID], [RowLog Contents 0], [Log Record], [RowLog Contents 1] FROM fn_dump_dblog ( @start_lsn, NULL, N'DISK', @seqno, @filename, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default) where [Current LSN] collate SQL_Latin1_General_CP1_CI_AS > @start_lsn_cmp collate SQL_Latin1_General_CP1_CI_AS and ( ( [operation] in ('LOP_BEGIN_XACT','LOP_COMMIT_XACT','LOP_ABORT_XACT') ) or ( [operation] in ('LOP_INSERT_ROWS','LOP_DELETE_ROWS','LOP_MODIFY_ROW') and ( ( [context] in ('LCX_HEAP','LCX_CLUSTERED','LCX_MARK_AS_GHOST') ) or ([context] = 'LCX_TEXT_MIX' and (datalength([RowLog Contents 0]) in (0,1)))) and [PartitionID] in ( select * from master.awsdms.split_partition_list (@partition_list,',')) ) or ([operation] = 'LOP_HOBT_DDL') ) else SELECT [Current LSN], [operation], [Context], [Transaction ID], [Transaction Name], [Begin Time], [End Time], [Flag Bits], [PartitionID], [Page ID], [Slot ID], [RowLog Contents 0], [Log Record], [RowLog Contents 1] — After Image FROM fn_dump_dblog ( @start_lsn, NULL, N'DISK', @seqno, @filename, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default) where [Current LSN] collate SQL_Latin1_General_CP1_CI_AS > @start_lsn_cmp collate SQL_Latin1_General_CP1_CI_AS and ( ( [operation] in ('LOP_BEGIN_XACT','LOP_COMMIT_XACT','LOP_ABORT_XACT') ) or ( [operation] in ('LOP_INSERT_ROWS','LOP_DELETE_ROWS','LOP_MODIFY_ROW') and ( ( [context] in ('LCX_HEAP','LCX_CLUSTERED','LCX_MARK_AS_GHOST') ) or ([context] = 'LCX_TEXT_MIX' and (datalength([RowLog Contents 0]) in (0,1)))) and ([PartitionID] is not null) and ([PartitionID] >= @minPartition and [PartitionID]<=@maxPartition) ) or ([operation] = 'LOP_HOBT_DDL') ) SET NOCOUNT OFF — Re-enable "rows affected display" end GO
  5. 使用下列指令碼在 Master 資料庫上建立憑證:

    Use [master] Go CREATE CERTIFICATE [awsdms_rtm_dump_dblog_cert] ENCRYPTION BY PASSWORD = N'@5trongpassword' WITH SUBJECT = N'Certificate for FN_DUMP_DBLOG Permissions';
  6. 使用下列指令碼從憑證建立登入:

    Use [master] Go CREATE LOGIN awsdms_rtm_dump_dblog_login FROM CERTIFICATE [awsdms_rtm_dump_dblog_cert];
  7. 使用下列指令碼將登入新增至 sysadmin 伺服器角色:

    ALTER SERVER ROLE [sysadmin] ADD MEMBER [awsdms_rtm_dump_dblog_login];
  8. 透過以下指令碼,使用該憑證將簽章新增至 [master].[awsdms].[rtm_dump_dblog]:

    Use [master] GO ADD SIGNATURE TO [master].[awsdms].[rtm_dump_dblog] BY CERTIFICATE [awsdms_rtm_dump_dblog_cert] WITH PASSWORD = '@5trongpassword';
    注意

    如果您重新建立預存程序,則需要再次新增簽章。

  9. 使用下列指令碼,在 Master 資料庫上建立 [awsdms].[rtm_position_1st_timestamp]:

    use [master] if object_id('[awsdms].[rtm_position_1st_timestamp]','P') is not null DROP PROCEDURE [awsdms].[rtm_position_1st_timestamp]; go create procedure [awsdms].[rtm_position_1st_timestamp] ( @dbname sysname, -- Database name @seqno integer, -- Backup set sequence/position number within file @filename varchar(260), -- The backup filename @1stTimeStamp varchar(40) -- The timestamp to position by ) as begin SET NOCOUNT ON -- Disable "rows affected display" declare @firstMatching table ( cLsn varchar(32), bTim datetime ) declare @sql nvarchar(4000) declare @nl char(2) declare @tb char(2) declare @fnameVar nvarchar(254) = 'NULL' set @nl = char(10); -- New line set @tb = char(9) -- Tab separator if (@filename is not null) set @fnameVar = ''''+@filename +'''' set @sql='use ['+@dbname+'];'+@nl+ 'select top 1 [Current LSN],[Begin Time]'+@nl+ 'FROM fn_dump_dblog (NULL, NULL, NULL, '+ cast(@seqno as varchar(10))+','+ @fnameVar+','+@nl+ @tb+'default, default, default, default, default, default, default,'+@nl+ @tb+'default, default, default, default, default, default, default,'+@nl+ @tb+'default, default, default, default, default, default, default,'+@nl+ @tb+'default, default, default, default, default, default, default,'+@nl+ @tb+'default, default, default, default, default, default, default,'+@nl+ @tb+'default, default, default, default, default, default, default,'+@nl+ @tb+'default, default, default, default, default, default, default,'+@nl+ @tb+'default, default, default, default, default, default, default,'+@nl+ @tb+'default, default, default, default, default, default, default)'+@nl+ 'where operation=''LOP_BEGIN_XACT''' +@nl+ 'and [Begin Time]>= cast('+''''+@1stTimeStamp+''''+' as datetime)'+@nl --print @sql delete from @firstMatching insert into @firstMatching exec sp_executesql @sql -- Get them all select top 1 cLsn as [matching LSN],convert(varchar,bTim,121) as [matching Timestamp] from @firstMatching; SET NOCOUNT OFF -- Re-enable "rows affected display" end GO
  10. 使用下列指令碼在 Master 資料庫上建立憑證:

    Use [master] Go CREATE CERTIFICATE [awsdms_rtm_position_1st_timestamp_cert] ENCRYPTION BY PASSWORD = '@5trongpassword' WITH SUBJECT = N'Certificate for FN_POSITION_1st_TIMESTAMP Permissions';
  11. 使用下列指令碼從憑證建立登入:

    Use [master] Go CREATE LOGIN awsdms_rtm_position_1st_timestamp_login FROM CERTIFICATE [awsdms_rtm_position_1st_timestamp_cert];
  12. 使用下列指令碼將登入新增至 sysadmin 角色:

    ALTER SERVER ROLE [sysadmin] ADD MEMBER [awsdms_rtm_position_1st_timestamp_login];
  13. 使用下列指令碼,使用該憑證將簽章新增至 [master].[awsdms].[rtm_position_1st_timestamp]:

    Use [master] GO ADD SIGNATURE TO [master].[awsdms].[rtm_position_1st_timestamp] BY CERTIFICATE [awsdms_rtm_position_1st_timestamp_cert] WITH PASSWORD = '@5trongpassword';
  14. 使用下列指令碼,授與使用DMS者對新預存程序的執行存取權:

    use master go GRANT execute on [awsdms].[rtm_position_1st_timestamp] to dms_user;
  15. 在下列每個資料庫中建立具有下列許可和角色的使用者:

    注意

    您應該在每個複本上建立相同SID的 dmsnosysadmin 使用者帳戶。下列SQL查詢可協助驗證每個複本上的 dmsnosysadmin 帳戶SID值。如需有關建立使用者的詳細資訊,請參閱 Microsoft SQL 伺服器說明文件中的 CREATEUSER(交易-SQL)。如需針對 Azure 資SQL料庫建立SQL使用者帳戶的詳細資訊,請參閱作用中異地複寫

    use master go grant select on sys.fn_dblog to [DMS_user] grant view any definition to [DMS_user] grant view server state to [DMS_user]—(should be granted to the login). grant execute on sp_repldone to [DMS_user] grant execute on sp_replincrementlsn to [DMS_user] grant execute on sp_addpublication to [DMS_user] grant execute on sp_addarticle to [DMS_user] grant execute on sp_articlefilter to [DMS_user] grant select on [awsdms].[split_partition_list] to [DMS_user] grant execute on [awsdms].[rtm_dump_dblog] to [DMS_user]
    use MSDB go grant select on msdb.dbo.backupset to [DMS_user] grant select on msdb.dbo.backupmediafamily to [DMS_user] grant select on msdb.dbo.backupfile to [DMS_user]

    在來源資料庫上執行下列指令碼:

    EXEC sp_addrolemember N'db_owner', N'DMS_user' use Source_DB go
  16. 最後,將額外的連線屬性 (ECA) 新增至來源SQL伺服器端點:

    enableNonSysadminWrapper=true;

在可用性群組環境中的SQL伺服器上設定持續複寫:沒有系統管理員角色

本節說明如何在不需要使用者帳戶擁有 sysadmin 權限的可用性群組環境中,為SQL伺服器資料庫來源設定持續複寫。

注意

執行本節中的步驟後,非系統管理員DMS使用者將擁有執行下列作業的權限:

  • 從線上交易記錄檔讀取變更

  • 從交易記錄備份檔讀取變更的磁碟存取權

  • 添加或更改使DMS用的出版物

  • 將文章新增至出版物

在可用群組環境中不使用 sysadmin 使用者的情況下設定進行中複寫
  1. 如中所述,設定用於複製的 Microsoft SQL 伺服器擷取資料變更,以便從SQL伺服器進行複寫

  2. 在來源資料庫REPLICATION上啟用 MS-。此操作可以手動完成,也可以透過使用 sysadmin 使用者執行任務一次來完成。

    注意

    您應該將 MS-REPLICATION 分發商配置為本地或允許通過關聯的鏈接服務器訪問非系統管理員用戶的方式。

  3. 如果已啟用 [在單一工作端點內專用 sp_repldone] 選項,請停止 MS-REPLICATION 記錄讀取器工作。

  4. 在每個複本上執行以下步驟:

    1. 在主資料庫中建立 [awsdms][awsdms] 結構描述:

      CREATE SCHEMA [awsdms]
    2. 在 Master 資料庫上建立 [awsdms].[split_partition_list] 資料表值函數:

      USE [master] GO SET ansi_nulls on GO SET quoted_identifier on GO IF (object_id('[awsdms].[split_partition_list]','TF')) is not null DROP FUNCTION [awsdms].[split_partition_list]; GO CREATE FUNCTION [awsdms].[split_partition_list] ( @plist varchar(8000), --A delimited list of partitions @dlm nvarchar(1) --Delimiting character ) RETURNS @partitionsTable table --Table holding the BIGINT values of the string fragments ( pid bigint primary key ) AS BEGIN DECLARE @partition_id bigint; DECLARE @dlm_pos integer; DECLARE @dlm_len integer; SET @dlm_len = len(@dlm); WHILE (charindex(@dlm,@plist)>0) BEGIN SET @dlm_pos = charindex(@dlm,@plist); SET @partition_id = cast( ltrim(rtrim(substring(@plist,1,@dlm_pos-1))) as bigint); INSERT into @partitionsTable (pid) values (@partition_id) SET @plist = substring(@plist,@dlm_pos+@dlm_len,len(@plist)); END SET @partition_id = cast (ltrim(rtrim(@plist)) as bigint); INSERT into @partitionsTable (pid) values ( @partition_id ); RETURN END GO
    3. 在 Master 資料庫上建立 [awsdms].[rtm_dump_dblog] 程序:

      USE [MASTER] GO IF (object_id('[awsdms].[rtm_dump_dblog]','P')) is not null DROP PROCEDURE [awsdms].[rtm_dump_dblog]; GO SET ansi_nulls on GO SET quoted_identifier on GO CREATE PROCEDURE [awsdms].[rtm_dump_dblog] ( @start_lsn varchar(32), @seqno integer, @filename varchar(260), @partition_list varchar(8000), -- A comma delimited list: P1,P2,... Pn @programmed_filtering integer, @minPartition bigint, @maxPartition bigint ) AS BEGIN DECLARE @start_lsn_cmp varchar(32); -- Stands against the GT comparator SET NOCOUNT ON -- Disable "rows affected display" SET @start_lsn_cmp = @start_lsn; IF (@start_lsn_cmp) is null SET @start_lsn_cmp = '00000000:00000000:0000'; IF (@partition_list is null) BEGIN RAISERROR ('Null partition list was passed',16,1); return --set @partition_list = '0,'; -- A dummy which is never matched END IF (@start_lsn) is not null SET @start_lsn = '0x'+@start_lsn; IF (@programmed_filtering=0) SELECT [Current LSN], [operation], [Context], [Transaction ID], [Transaction Name], [Begin Time], [End Time], [Flag Bits], [PartitionID], [Page ID], [Slot ID], [RowLog Contents 0], [Log Record], [RowLog Contents 1] -- After Image FROM fn_dump_dblog ( @start_lsn, NULL, N'DISK', @seqno, @filename, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default) WHERE [Current LSN] collate SQL_Latin1_General_CP1_CI_AS > @start_lsn_cmp collate SQL_Latin1_General_CP1_CI_AS -- This aims for implementing FN_DBLOG based on GT comparator. AND ( ( [operation] in ('LOP_BEGIN_XACT','LOP_COMMIT_XACT','LOP_ABORT_XACT') ) OR ( [operation] in ('LOP_INSERT_ROWS','LOP_DELETE_ROWS','LOP_MODIFY_ROW') AND ( ( [context] in ('LCX_HEAP','LCX_CLUSTERED','LCX_MARK_AS_GHOST') ) or ([context] = 'LCX_TEXT_MIX') ) AND [PartitionID] in ( select * from master.awsdms.split_partition_list (@partition_list,',')) ) OR ([operation] = 'LOP_HOBT_DDL') ) ELSE SELECT [Current LSN], [operation], [Context], [Transaction ID], [Transaction Name], [Begin Time], [End Time], [Flag Bits], [PartitionID], [Page ID], [Slot ID], [RowLog Contents 0], [Log Record], [RowLog Contents 1] -- After Image FROM fn_dump_dblog ( @start_lsn, NULL, N'DISK', @seqno, @filename, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default, default) WHERE [Current LSN] collate SQL_Latin1_General_CP1_CI_AS > @start_lsn_cmp collate SQL_Latin1_General_CP1_CI_AS -- This aims for implementing FN_DBLOG based on GT comparator. AND ( ( [operation] in ('LOP_BEGIN_XACT','LOP_COMMIT_XACT','LOP_ABORT_XACT') ) OR ( [operation] in ('LOP_INSERT_ROWS','LOP_DELETE_ROWS','LOP_MODIFY_ROW') AND ( ( [context] in ('LCX_HEAP','LCX_CLUSTERED','LCX_MARK_AS_GHOST') ) or ([context] = 'LCX_TEXT_MIX') ) AND ([PartitionID] is not null) and ([PartitionID] >= @minPartition and [PartitionID]<=@maxPartition) ) OR ([operation] = 'LOP_HOBT_DDL') ) SET NOCOUNT OFF -- Re-enable "rows affected display" END GO
    4. 在 Master 資料庫上建立憑證:

      USE [master] GO CREATE CERTIFICATE [awsdms_rtm_dump_dblog_cert] ENCRYPTION BY PASSWORD = N'@hardpassword1' WITH SUBJECT = N'Certificate for FN_DUMP_DBLOG Permissions'
    5. 從憑證建立登入:

      USE [master] GO CREATE LOGIN awsdms_rtm_dump_dblog_login FROM CERTIFICATE [awsdms_rtm_dump_dblog_cert];
    6. 將登入新增至 sysadmin 伺服器角色:

      ALTER SERVER ROLE [sysadmin] ADD MEMBER [awsdms_rtm_dump_dblog_login];
    7. 透過此憑證,將簽章新增至 [master].[awsdms].[rtm_dump_dblog] 程序:

      USE [master] GO ADD SIGNATURE TO [master].[awsdms].[rtm_dump_dblog] BY CERTIFICATE [awsdms_rtm_dump_dblog_cert] WITH PASSWORD = '@hardpassword1';
      注意

      如果您重新建立預存程序,則需要再次新增簽章。

    8. 在 Master 資料庫上建立 [awsdms].[rtm_position_1st_timestamp] 程序:

      USE [master] IF object_id('[awsdms].[rtm_position_1st_timestamp]','P') is not null DROP PROCEDURE [awsdms].[rtm_position_1st_timestamp]; GO CREATE PROCEDURE [awsdms].[rtm_position_1st_timestamp] ( @dbname sysname, -- Database name @seqno integer, -- Backup set sequence/position number within file @filename varchar(260), -- The backup filename @1stTimeStamp varchar(40) -- The timestamp to position by ) AS BEGIN SET NOCOUNT ON -- Disable "rows affected display" DECLARE @firstMatching table ( cLsn varchar(32), bTim datetime ) DECLARE @sql nvarchar(4000) DECLARE @nl char(2) DECLARE @tb char(2) DECLARE @fnameVar sysname = 'NULL' SET @nl = char(10); -- New line SET @tb = char(9) -- Tab separator IF (@filename is not null) SET @fnameVar = ''''+@filename +'''' SET @filename = ''''+@filename +'''' SET @sql='use ['+@dbname+'];'+@nl+ 'SELECT TOP 1 [Current LSN],[Begin Time]'+@nl+ 'FROM fn_dump_dblog (NULL, NULL, NULL, '+ cast(@seqno as varchar(10))+','+ @filename +','+@nl+ @tb+'default, default, default, default, default, default, default,'+@nl+ @tb+'default, default, default, default, default, default, default,'+@nl+ @tb+'default, default, default, default, default, default, default,'+@nl+ @tb+'default, default, default, default, default, default, default,'+@nl+ @tb+'default, default, default, default, default, default, default,'+@nl+ @tb+'default, default, default, default, default, default, default,'+@nl+ @tb+'default, default, default, default, default, default, default,'+@nl+ @tb+'default, default, default, default, default, default, default,'+@nl+ @tb+'default, default, default, default, default, default, default)'+@nl+ 'WHERE operation=''LOP_BEGIN_XACT''' +@nl+ 'AND [Begin Time]>= cast('+''''+@1stTimeStamp+''''+' as datetime)'+@nl --print @sql DELETE FROM @firstMatching INSERT INTO @firstMatching exec sp_executesql @sql -- Get them all SELECT TOP 1 cLsn as [matching LSN],convert(varchar,bTim,121) AS[matching Timestamp] FROM @firstMatching; SET NOCOUNT OFF -- Re-enable "rows affected display" END GO
    9. 在 Master 資料庫上建立憑證:

      USE [master] GO CREATE CERTIFICATE [awsdms_rtm_position_1st_timestamp_cert] ENCRYPTION BY PASSWORD = N'@hardpassword1' WITH SUBJECT = N'Certificate for FN_POSITION_1st_TIMESTAMP Permissions';
    10. 從憑證建立登入:

      USE [master] GO CREATE LOGIN awsdms_rtm_position_1st_timestamp_login FROM CERTIFICATE [awsdms_rtm_position_1st_timestamp_cert];
    11. 將登入新增至 sysadmin 伺服器角色:

      ALTER SERVER ROLE [sysadmin] ADD MEMBER [awsdms_rtm_position_1st_timestamp_login];
    12. 使用憑證將簽章新增至 [master].[awsdms].[rtm_position_1st_timestamp] 程序:

      USE [master] GO ADD SIGNATURE TO [master].[awsdms].[rtm_position_1st_timestamp] BY CERTIFICATE [awsdms_rtm_position_1st_timestamp_cert] WITH PASSWORD = '@hardpassword1';
      注意

      如果您重新建立預存程序,則需要再次新增簽章。

    13. 在下列每個資料庫中建立具有下列許可/角色的使用者:

      注意

      您應該在每個複本上建立相同SID的 dmsnosysadmin 使用者帳戶。下列SQL查詢可協助驗證每個複本上的 dmsnosysadmin 帳戶SID值。如需有關建立使用者的詳細資訊,請參閱 Microsoft SQL 伺服器說明文件中的 CREATEUSER(交易-SQL)。如需針對 Azure 資SQL料庫建立SQL使用者帳戶的詳細資訊,請參閱作用中異地複寫

      SELECT @@servername servername, name, sid, create_date, modify_date FROM sys.server_principals WHERE name = 'dmsnosysadmin';
    14. 在每個複本的主資料庫上授予許可:

      USE master GO GRANT select on sys.fn_dblog to dmsnosysadmin; GRANT view any definition to dmsnosysadmin; GRANT view server state to dmsnosysadmin -- (should be granted to the login). GRANT execute on sp_repldone to dmsnosysadmin; GRANT execute on sp_replincrementlsn to dmsnosysadmin; GRANT execute on sp_addpublication to dmsnosysadmin; GRANT execute on sp_addarticle to dmsnosysadmin; GRANT execute on sp_articlefilter to dmsnosysadmin; GRANT select on [awsdms].[split_partition_list] to dmsnosysadmin; GRANT execute on [awsdms].[rtm_dump_dblog] to dmsnosysadmin; GRANT execute on [awsdms].[rtm_position_1st_timestamp] to dmsnosysadmin;
    15. 在每個複本上 msdb 資料庫授予許可:

      USE msdb GO GRANT select on msdb.dbo.backupset to dmsnosysadmin GRANT select on msdb.dbo.backupmediafamily to dmsnosysadmin GRANT select on msdb.dbo.backupfile to dmsnosysadmin
    16. db_owner 角色新增至 dmsnosysadmin 來源資料庫。由於資料庫已同步處理,因此您只能在主要複本上新增角色。

      use <source DB> GO EXEC sp_addrolemember N'db_owner', N'dmsnosysadmin'

在雲端SQL伺服器資料庫執行個體上設定持續複寫

本節說明如何在雲端裝載的SQL伺服器資料庫執行個體CDC上進行設定。雲端託管SQL伺服器執行個體是在 Amazon RDS 適用於SQL伺服器、Azure SQL 受管理的執行個體或任何其他受管雲端伺服SQL器執行個體上執行的執行個體。如需每種資料庫類型之進行中複寫限制的相關資訊,請參閱使用伺SQL服器做為來源的限制 AWS DMS

在設定進行中複寫之前,請參閱從SQL伺服器來源使用進行中複寫 (CDC) 的先決條件

與自我管理的 Microsoft SQL 伺服器來源不同,Amazon RDS SQL 伺服器版不支援 MS 複寫。因此, AWS DMS 需要使用 MS-用CDC於有或不帶主鍵的表。

Amazon RDS 不會授與系統管理員權限來設定 AWS DMS 用於來源SQL伺服器執行個體中持續變更的複寫成品。請務必為 Amazon RDS 執行個體開啟 MS-CDC (使用主要使用者權限),如下列程序所示。

為雲端SQL伺服器資料庫執CDC行個體開啟 MS-
  1. 在資料庫層級執行以下其中一種查詢。

    對於SQL伺服器RDS資料庫執行個體,請使用此查詢。

    exec msdb.dbo.rds_cdc_enable_db 'DB_name'

    對於 Azure SQL 受控資料庫執行個體,請使用此查詢。

    USE DB_name GO EXEC sys.sp_cdc_enable_db GO
  2. 對於具有主鍵的每個表,運行以下查詢以打開 MS-CDC。

    exec sys.sp_cdc_enable_table @source_schema = N'schema_name', @source_name = N'table_name', @role_name = NULL, @supports_net_changes = 1 GO

    對於每個具有唯一鍵但沒有主鍵的表,運行以下查詢以打開 MS-CDC。

    exec sys.sp_cdc_enable_table @source_schema = N'schema_name', @source_name = N'table_name', @index_name = N'unique_index_name', @role_name = NULL, @supports_net_changes = 1 GO

    對於沒有主鍵或唯一鍵的每個表,運行以下查詢打開 MS-CDC。

    exec sys.sp_cdc_enable_table @source_schema = N'schema_name', @source_name = N'table_name', @role_name = NULL GO
  3. 設定保留期間:

    • 對RDS於使用 3.5.3 版及更新DMS版本進行複製的SQL伺服器執行個體,請確定保留期間設定為預設值 5 秒。如果您要從 DMS 3.5.2 及更低版本升級或移至 DMS 3.5.3 及更新版本,請在新的或升級的執行個體上執行工作後變更輪詢間隔值。下列指令碼會將保留期間設定為 5 秒:

      use dbname EXEC sys.sp_cdc_change_job @job_type = 'capture' ,@pollinginterval = 5 exec sp_cdc_stop_job 'capture' exec sp_cdc_start_job 'capture'
    • 對於 Azure SQL MI 以及使RDS用 3.5.2 及更DMS新版本複寫的SQL伺服器執行個體,請使用下列命令:

      use dbname EXEC sys.sp_cdc_change_job @job_type = 'capture' ,@pollinginterval = 86399 exec sp_cdc_stop_job 'capture' exec sp_cdc_start_job 'capture'

      參數 @pollinginterval 的測量單位為秒,建議值設定為 86399。這表示當 @pollinginterval = 86399 時,交易日誌會保留變更 86,399 秒 (一天)。此程序 exec sp_cdc_start_job 'capture' 會啟動設定。

      注意

      對於某些版本的SQL伺服器,如果的值設定pollinginterval為超過 3599 秒,則值會重設為預設值 5 秒。發生這種情況時,T-Log 條目會先清除,然後才 AWS DMS 能讀取它們。若要判斷哪些SQL伺服器版本會受到這個已知問題的影響,請參閱這篇 Microsoft 知識庫文章

      如果您將 Amazon RDS 與異地同步備份搭配使用,請確保您還將次要設定為具有正確的值,以防容錯移轉。

      exec rdsadmin..rds_set_configuration 'cdc_capture_pollinginterval' , <5 or 86399>
若要維持 AWS DMS 複寫工作停止超過一小時的保留期
注意

對於使用 DMS 3.5.3 及更高版本的SQL伺服RDS器來源複製,不需要下列步驟。

  1. 使用以下命令,停止截斷交易日誌的任務。

    exec sp_cdc_stop_job 'capture'
  2. 在 AWS DMS 控制台上找到您的任務並繼續任務。

  3. 選擇監控索引標籤,接著勾選 CDCLatencySource 指標。

  4. 一旦 CDCLatencySource 指標等於 0 (零) 並停在該階段,請使用下列命令重新開始截斷交易日誌的作業。

    exec sp_cdc_start_job 'capture'

請記得啟動截斷SQL伺服器交易記錄的工作。否則,SQL伺服器執行個體上的儲存空間可能會填滿。

將SQL伺服器作為來源使用時RDS的建議設定 AWS DMS

對於 AWS DMS 3.5.3 及以上

注意

根據預設,RDS針對您在 3.5.3 版發行之後建立或修改的端點,會啟用用於SQL伺服器記錄檔備份功能的初始DMS版本。若要對現有端點使用此功能,請修改端點而不進行任何變更。

AWS DMS 版本 3.5.3 引入了從日誌備份讀取的支持。DMS主要仰賴從使用中交易記錄檔讀取來複寫事件。如果交易已備份之前DMS可以從使用中記錄檔讀取該交易,則工作會依需求存取RDS備份,並從後續備份記錄讀取,直到它抓到作用中的交易記錄為止。若要確DMS保可存取記錄備份,請將RDS自動備份保留期限設定為至少一天。如需設定自動 Backup 保留期的相關資訊,請參閱 Amazon RDS 使用者指南中的備份保留期

存取記錄備份的DMS工作會利用執行個RDS體上的儲存空間。請注意,此工作只會存取複寫所需的記錄備份。Amazon RDS 會在幾個小時內刪除這些下載的備份。這項移除不會影響 Amazon S3 中保留的 Amazon RDS 備份或亞馬遜RDSRESTORE DATABASE功能。如果您打算使用進行複製,建議在您RDS的SQL服務器源上分配額外的存儲DMS。估計所需儲存容量的一種方法是識別從中開始或繼續複寫的備份,並使用RDStlog backup中繼資料功能DMS將所有後續備份的檔案大小加起來。如需有關此tlog backup功能的詳細資訊,請參閱 Amazon RDS 使用者指南中的列出可用交易記錄備份

或者,您可以根據 Amazon 執行個體的指標選擇啟用儲存自動調 CloudWatch FreeStorageSpace度資源和/或觸發儲存擴展。RDS

我們強烈建議您不要從交易記錄檔備份中的某個點開始或繼續,因為這可能會導致SQL伺服器執行個體上的儲存空間已滿。在這種情況下,最好是啟動滿負荷。從交易記錄檔備份複寫會比從使用中交易記錄檔讀取慢。如需詳細資訊,請參閱SQL伺服器的RDS交易記錄備份處理

請注意,存取記錄備份需要額外的權限。如需詳細資訊,請參閱在工作開始複寫之前設定從雲端SQL伺服器資料庫進行複寫的權限 確定您已授與這些權限中的詳細資訊。

對於 AWS DMS 3.5.2 及以下

當您使用 Amazon RDS SQL 服務器作為源時,MS-CDC 捕獲任務依賴於參數maxscansmaxtrans. 這些參數會控制 MS-CDC 擷取在交易記錄檔上執行的掃描數目上限,以及針對每個掃描處理的交易數目。

對於交易數目大於 maxtrans*maxscans 的資料庫,提高 polling_interval 值可能會導致作用中交易日誌記錄不斷累積。反過來,此累積會導致交易日誌變大。

請注意, AWS DMS 不依賴於 MS-CDC 捕獲作業。MS-CDC 捕獲作業將事務日誌條目標記為已處理。這可讓交易日誌備份作業從交易日誌中移除項目。

我們建議您監視事務日誌的大小和 MS-CDC 作業的成功。如果 MS-CDC 作業失敗,交易記錄檔可能會過度成長,並造成 AWS DMS 複寫失敗。您可以使用來源資料庫中的sys.dm_cdc_errors動態管理檢視來監視 MS-CDC 擷取工作錯誤。您可以使用 DBCC SQLPERF(LOGSPACE) 管理命令來監控交易日誌大小。

為了解決由 MS 引起的事務日誌增加-CDC
  1. 檢查資Log Space Used %料庫 AWS DMS 是否正在從中複製,並驗證資料庫是否持續增加。

    DBCC SQLPERF(LOGSPACE)
  2. 識別封鎖交易日誌備份程序的項目。

    Select log_reuse_wait, log_reuse_wait_desc, name from sys.databases where name = db_name();

    如果log_reuse_wait_desc值等於REPLICATION,則記錄備份保留是由 MS-中的延遲所造成CDC。

  3. 增加 maxtransmaxscans 參數值,以提高擷取作業所處理的事件數目。

    EXEC sys.sp_cdc_change_job @job_type = 'capture' ,@maxtrans = 5000, @maxscans = 20 exec sp_cdc_stop_job 'capture' exec sp_cdc_start_job 'capture'

若要解決這個問題,請設定maxscans和的值等maxtrans*maxscans於每天從來源資料庫 AWS DMS 複寫之表格maxtrans所產生的平均事件數目。

如果您將這些參數設定為高於建議值,擷取作業會處理交易日誌中的所有事件。如果您將這些參數設定為低於建議值,MS-CDC 延遲會增加,而且交易記錄檔也會增加。

由於工作負載中的變更會產生不同數量的事件,因此找出 maxscansmaxtrans 適當的值可能很困難。在這種情況下,我們建議您在 MS-CDC 延遲上設置監視。如需詳細資訊,請參閱SQL伺服器文件中的監視處理序。然後根據監控結果動態設定 maxtransmaxscans

如果 AWS DMS 工作無法找到繼續或繼續工作所需的記錄序號 (LSNs),則工作可能會失敗並需要完全重新載入。

注意

使用 AWS DMS 從 SQL Server 來源複寫資料時,在 Amazon RDS 執行個RDS體的停止啟動事件之後嘗試繼續複寫時,可能會遇到錯誤。這是因為SQL伺服器代理程式處理序會在停止啟動事件之後重新啟動擷取工作處理序時重新啟動。這會略過 MS CDC 輪詢間隔。

因此,在交易磁碟區低於 MS-CDC 擷取工作處理的資料庫上,這可能會導致資料被處理或標記為已複寫和備份,然後才 AWS DMS 能從停止的位置繼續進行,導致下列錯誤:

[SOURCE_CAPTURE ]E: Failed to access LSN '0000dbd9:0006f9ad:0003' in the backup log sets since BACKUP/LOG-s are not available. [1020465] (sqlserver_endpoint_capture.c:764)

若要緩解此問題,請依照先前的建議設定 maxtransmaxscans 值。