CDC 用に Cloud SQL for SQL Server データベースを構成する

変更データ キャプチャ(CDC)の更新を サポートされている宛先(BigQuery や Cloud Storage など)にストリーミングするには、Cloud SQL for SQL Server データベースを Datastream に接続します。データベースとテーブルで CDC を有効にし、スナップショット分離を有効にして、Datastream ユーザーを構成します。トランザクション ログの CDC メソッドを使用する場合は、ログの保持を構成し、ポイントインタイム リカバリを有効にします。

移行元インスタンスを構成する手順は次のとおりです。

  1. Cloud SQL インスタンスに接続します。これを行うには、Cloud Shell プロンプトで gcloud sql connect コマンドを使用します。

  2. 次のコマンドを実行して、データベースで CDC を有効にします。

    EXEC msdb.dbo.gcloudsql_cdc_enable_db 'DATABASE_NAME'
    

    DATABASE_NAME は、ソース データベースの名前に置き換えます。

  3. 変更を取得する必要があるテーブルで CDC を有効にします。

    USE [DATABASE_NAME]
    EXEC sys.sp_cdc_enable_table
    @source_schema = N'SCHEMA_NAME',
    @source_name = N'TABLE_NAME',
    @role_name = NULL
    GO
    
  4. スナップショット分離を有効にします。

    SQL Server データベースからデータをバックフィルする際は、整合性のあるスナップショットを確保することが重要です。このセクションで説明している設定を適用しない場合、バックフィル プロセス中にデータベースに加えた変更により、重複や誤った結果が生じる可能性があります。ストリームに主キーのないテーブルが含まれている場合は、スナップショット分離の設定を適用する必要があります。

    スナップショット分離を有効にすると、バックフィル プロセスの開始時にデータベースの一時ビューが作成されます。これにより、他のユーザーが同時にライブテーブルに変更を加えた場合でも、コピーされるデータの整合性が確実に維持されます。スナップショット分離を有効にすると、パフォーマンスにわずかな影響を与える可能性がありますが、信頼性の高いデータ抽出には不可欠です。

    スナップショット分離を有効にするには:

    1. SQL Server クライアントを使用してデータベースに接続します。
    2. 次のコマンドを実行します。
    ALTER DATABASE DATABASE_NAME SET ALLOW_SNAPSHOT_ISOLATION ON;
    

    DATABASE_NAME は、データベースの名前に置き換えます。

  5. Datastream ユーザーを作成する:

    1. コンソール Google Cloud で、[Cloud SQL のインスタンス] ページに移動します。

      Cloud SQL の [インスタンス] に移動

    2. ユーザーを作成し、db_owner ロールと db_denydatawriter ロールを割り当てます。

    CREATE USER USER_NAME FOR LOGIN YOUR_LOGIN;
    
    EXEC sp_addrolemember 'db_owner', 'USER_NAME';
    EXEC sp_addrolemember 'db_denydatawriter', 'USER_NAME';
    

トランザクション ログの CDC メソッドに必要な追加手順

このセクションで説明する手順は、トランザクション ログ の CDC メソッドで使用するためにソース SQL Server データベースを構成する場合にのみ必要です。

  1. ソースで変更を有効にするポーリング間隔を設定します。

    USE [DATABASE_NAME]
    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 に設定されています。つまり、トランザクション ログは、86,399 秒間(1 日)変更を保持します。sp_cdc_start_job 'capture プロシージャを実行すると、設定が開始されます。

  2. ログの切り捨ての防止対策を設定します。

    CDC のリーダーがログの読み取りに十分な時間を確保しながら、ログの切り捨てによって保存容量が不足しないようにするには、ログの切り捨ての防止対策を設定します。

    1. SQL Server クライアントを使用してデータベースに接続します。
    2. データベースにダミーテーブルを作成します。

      USE [DATABASE_NAME];
      CREATE TABLE dbo.gcp_datastream_truncation_safeguard (
        [id] INT IDENTITY(1,1) PRIMARY KEY,
        CreatedDate DATETIME DEFAULT GETDATE(),
        [char_column] CHAR(8)
        );
      
    3. ログの切り捨てを防止するために指定した期間にアクティブなトランザクションを実行するストアド プロシージャを作成します。

      CREATE PROCEDURE [dbo].[DatastreamLogTruncationSafeguard] @transaction_logs_retention_time INT
      AS
      BEGIN
        -- Start a new transaction
        BEGIN TRANSACTION;
        INSERT INTO dbo.gcp_datastream_truncation_safeguard (char_column) VALUES ('a')
      
      DECLARE @formatted_time VARCHAR(5)
      SET @formatted_time = CONVERT(VARCHAR(5), DATEADD(MINUTE, @transaction_logs_retention_time, 0), 108);
        -- Wait for X minutes before ending the transaction
        WAITFOR DELAY @formatted_time;
        -- Commit the transaction
        COMMIT TRANSACTION;
      END;
      
    4. 別のストアド プロシージャを作成します。今回は、前の手順で作成したストアド プロシージャを指定した間隔に従って実行するジョブを作成します。

      CREATE PROCEDURE [dbo].[SetUpDatastreamJob] @transaction_logs_retention_time INT
      AS
      BEGIN
        DECLARE @database_name VARCHAR(MAX)
        SET @database_name =  (SELECT DB_NAME());;
      
        DECLARE @command_str VARCHAR(MAX);
        SET @command_str = CONCAT('Use ', @database_name,'; exec dbo.DatastreamLogTruncationSafeguard @transaction_logs_retention_time = ' + CAST(@transaction_logs_retention_time AS VARCHAR(10)));
      
        DECLARE @job_name VARCHAR(MAX);
      SET @job_name =
        CONCAT(@database_name, '_', 'DatastreamLogTruncationSafeguardJob1')
      
          -- Add 3 schedules to the job to run again after specified time.
          IF
            NOT EXISTS(
              SELECT *
              FROM msdb.dbo.sysjobs
              WHERE name = @job_name
            )
              BEGIN
                EXEC
                  msdb.dbo.sp_add_job
                    @job_name
        = @job_name,
        @enabled = 1,
        @description = N'Execute the procedure to run an active transaction for x minutes.';
      
      EXEC msdb.dbo.sp_add_jobstep @job_name = @job_name,
      @step_name = N'Execute_DatastreamLogTruncationSafeguard',
      @subsystem = N'TSQL',
      @command = @command_str;
      
        -- Add a schedule that runs the stored procedure every given minutes starting now.
        DECLARE @schedule_name_1 VARCHAR(MAX);
        SET @schedule_name_1 = CONCAT(@database_name, '_', 'DatastreamEveryGivenMinutesFromNow')
      
        DECLARE @start_time_1 time;
        SET @start_time_1 = DATEADD(SECOND, 1, GETDATE());
        DECLARE @formatted_start_time_1 INT;
        SET @formatted_start_time_1 = CONVERT(INT, REPLACE(CONVERT(VARCHAR(8), @start_time_1, 114), ':' ,''));
      
        EXEC msdb.dbo.sp_add_schedule
        @schedule_name = @schedule_name_1,
        @freq_type = 4,  -- daily start
        @freq_subday_type = 4,  -- every X minutes daily
        @freq_interval = 1,
        @freq_subday_interval = @transaction_logs_retention_time,
        @active_start_time = @formatted_start_time_1;
      
        EXEC msdb.dbo.sp_attach_schedule
        @job_name = @job_name,
        @schedule_name = @schedule_name_1 ;
      
        -- Add a schedule that runs the stored procedure after every given minutes starting after some delay.
        DECLARE @schedule_name_2 VARCHAR(MAX);
        Set @schedule_name_2 = CONCAT(@database_name, '_', 'DatastreamEveryGivenMinutesAfterDelay');
      
        DECLARE @start_time_2 time;
        SET @start_time_2 = DATEADD(MINUTE, @transaction_logs_retention_time / 2, GETDATE());
      
        DECLARE @formatted_start_time_2 INT;
        SET @formatted_start_time_2 = CONVERT(INT, REPLACE(CONVERT(VARCHAR(8), @start_time_2, 114), ':' ,''));
      
        EXEC msdb.dbo.sp_add_schedule
        @schedule_name = @schedule_name_2,
        @freq_type = 4,  -- daily start
        @freq_subday_type = 4,  -- every x minutes daily
        @freq_interval = 1,
        @freq_subday_interval = @transaction_logs_retention_time,
        @active_start_time = @formatted_start_time_2;
      
        EXEC msdb.dbo.sp_attach_schedule
        @job_name = @job_name,
        @schedule_name = @schedule_name_2 ;
      
        -- Add a schedule that runs the stored procedure on the SQL Server Agent startup.
        DECLARE @schedule_name_agent_startup VARCHAR(MAX);
        Set @schedule_name_agent_startup = CONCAT(@database_name, '_', 'DatastreamSqlServerAgentStartupSchedule')
      
        EXEC msdb.dbo.sp_add_schedule
        @schedule_name = @schedule_name_agent_startup,
        @freq_type = 64,  -- start on SQL Server Agent startup
        @active_start_time = @formatted_start_time_1;
      
        EXEC msdb.dbo.sp_attach_schedule
        @job_name = @job_name,
        @schedule_name = @schedule_name_agent_startup ;
      
        EXEC msdb.dbo.sp_add_jobserver
        @job_name = @job_name,
        @server_name = @@servername ;
        END
      END;
      
    5. データストリーム ジョブを作成するストアド プロシージャを実行します。

      DECLARE @transaction_logs_retention_time INT = (INT)
      EXEC [dbo].[SetUpDatastreamJob] @transaction_logs_retention_time
      

      INT は、ログを保持する時間(分単位)に置き換えます。次に例を示します。

      • 値が 60 の場合、保持期間は 1 時間です。
      • 値が 24 * 60 の場合、保持期間は 1 日です。
      • 値が 3 * 24 * 60 の場合、保持期間は 3 日です。
  3. ポイントインタイム リカバリ(PITR)を有効にします。

次のステップ