sql >> データベース >  >> RDS >> Database

リカバリが遅延したログ配布を使用したデータ損失の修正

    はじめに

    トランザクションログ配布は、ディザスタリカバリサイトでライブデータベースのコピーを維持するためにSQLServerで使用される非常によく知られたテクノロジです。このテクノロジは、バックアップジョブ、コピージョブ、および復元ジョブの3つの主要なジョブに依存しています。バックアップジョブがプライマリサーバーで実行されている間、コピーおよび復元ジョブはセカンダリサーバーで実行されます。基本的に、このプロセスには、コピージョブがセカンダリサーバーに移動する共有への定期的なトランザクションログのバックアップが含まれます。その後、復元ジョブはログバックアップをセカンダリサーバーに適用します。これをすべて開始する前に、NORECOVERYオプションを使用して復元されたプライマリサーバーからの完全バックアップを使用して、セカンダリデータベースを初期化する必要があります。

    Microsoftは、ログ配布をエンドツーエンドで構成するために使用できる一連のストアドプロシージャと、ログ配布を構成する可能性のある各データベースのプロパティ項目から始まる同等のGUIを提供しています。セカンダリデータベースは、NORECOVERYモードまたはSTANDBYモードで構成できることに注意してください。 NORECOVERYモードでは、データベースをクエリに使用できることはありませんが、STANDBYモードでは、トランザクションログの復元操作が進行中でないときにセカンダリデータベースをクエリできます。

    環境の設定

    ボールを転がすために、AWS上に同一のAmazonEC2イメージを使用して2つのSQLServerインスタンスを作成します。このAmazonEC2インスタンスは、WindowsServer2016でSQLServer2017 RTM-CU5を実行しています。次に、GitHubから取得したバックアップセットを使用して、WideWorldImportersデータベースのコピーを最初のインスタンスであるプライマリインスタンスに復元します。同じバックアップセットを使用して、BranchDBとCorporateDBという名前の2つの同一のデータベースを作成します。

    図。 1SQLServerバージョン

    図。 2プライマリインスタンス上のBranchDBとCorporateDB(セカンダリインスタンスは空白)

    リスト1:WideWorldImportersサンプルデータベースの復元

    restore filelistonly from disk='WideWorldImporters-Full.bak'
    
    restore database CorporateDB from disk='WideWorldImporters-Full.bak' with stats=10,recovery,
    
    move 'WWI_Primary' to 'M:\MSSQL\Data\WWI_Primary.mdf' , move 'WWI_UserData' to 'M:\MSSQL\Data\WWI_UserData.ndf' , move 'WWI_Log' to 'N:\MSSQL\Log\WWI_Log.ldf',
    
    move 'WWI_InMemory_Data_1' to 'M:\MSSQL\Data\WWI_InMemory_Data_1.ndf'
    
    restore database BranchDB from disk='WideWorldImporters-Full.bak' with stats=10,recovery,
    
    move 'WWI_Primary' to 'M:\MSSQL\Data\WWI_Primary1.mdf' , move 'WWI_UserData' to 'M:\MSSQL\Data\WWI_UserData1.ndf' , move 'WWI_Log' to 'N:\MSSQL\Log\WWI_Log1.ldf',
    
    move 'WWI_InMemory_Data_1' to 'M:\MSSQL\Data\WWI_InMemory_Data_11.ndf
    に移動します。

    これで、2つのインスタンスができました。プライマリインスタンスは2つのプライマリデータベース(BranchDBとCorporateDB、およびユーザーデータベースのないセカンダリインスタンス)をホストします。両方のデータベースでトランザクションログ配布の構成を続行しますが、復元構成に遅延を適用することで区別します。最初のデータベース。データベースには、含まれるデータに関して実際には同一であることを思い出してください。次の図は、ログ配布構成で選択された主要なオプションを示しています。

    図。 3BranchDBのバックアップ設定

    図。 4BranchDBの設定をコピーする

    図。 5BranchDBの設定を復元する

    各ログ配布ジョブは、5分ごとに実行するように構成されています。 「バックアップの遅延復元」を処理するには、ログ配布構成でスタンバイリカバリモードを使用する必要があります。セカンダリデータベースがスタンバイモードであり、トランザクションログの復元が進行中でないときはいつでもセカンダリデータベースにクエリを実行できることを示しているため、これは論理的です。このオプションで指定する値(この場合は30分)は、ユーザーエラーから回復できるこの記事のコア要件とは別に、セカンダリデータベースからレポートを実行できる適切なウィンドウを提供します。

    >

    また、トランザクションログバックアップの復元が実際に遅れていることにも言及する必要があります。そのタイムスタンプは遅延値よりも遅いです。これは、すべてのトランザクションログバックアップが、スケジュールに基づいてコピージョブで指定されたセカンダリサーバーにコピーされることを意味します。実際、復元ジョブは引き続きスケジュールどおりに実行されますが、トランザクションログのバックアップ(30分以内)は復元されません。基本的に、BranchDBスタンバイデータベースはBranchDBプライマリデータベースより30分遅れています。この遅れを示すために、次のセクションでは、両方のデータベースにテーブルを作成し、1分ごとにレコードを挿入するジョブを作成します。このテーブルをセカンダリデータベースで調べます。

    CorporateDBデータベースの設定は、図1および2と同じです。トランザクションログのバックアップを遅らせるように設定されていない復元ジョブを除いて、3〜5。

    図。 6CorporateDBの設定を復元する

    構成の確認

    構成が完了したら、構成に問題がないことを確認し、その作業の観察から始めることができます。トランザクションログ配布レポートは、ブランチDBが復元に関してCorporateDBよりも実際に遅れていることを示しています。

    図。 7aプライマリサーバーでのトランザクションログ配布レポート

    図。 7bセカンダリサーバーでのトランザクションログ配布レポート

    さらに、BranchDBのジョブの復元履歴に以下のメッセージが表示されます。

    図8セカンダリサーバーでスキップされたトランザクションログの復元

    テーブルを作成し、ジョブを使用してこのテーブルに1分ごとに行を入力することで、この検証をさらに進めることができます。このジョブは、アプリケーションがユーザーテーブルに対して実行している可能性のあることをシミュレートする簡単な方法です。これは、このラグがユーザーデータに明確に示されていることを示しています。

    リスト2–ログトラッカーテーブルの作成

    use BranchDB
    
    go
    
    create table log_ship_tracker
    
    ( ID int identity (100,1)
    
    ,Database_Name sysname default db_name()
    
    ,RecordTime datetime default getdate()
    
    ,ServerName sysname default @@servername)
    
    
    
    use CorporateDB
    
    go
    
    create table log_ship_tracker
    
    ( ID int identity (100,1)
    
    ,Database_Name sysname default db_name()
    
    ,RecordTime datetime default getdate()
    
    ,ServerName sysname default @@servername)

    リスト3–ログトラッカーテーブルに入力するジョブを作成する

    /* ==Scripting Parameters==
    
    Source Server Version : SQL Server 2017 (14.0.3023)
    Source Database Engine Edition : Microsoft SQL Server Standard Edition
    Source Database Engine Type : Standalone SQL Server
    
    Target Server Version : SQL Server 2017
    
    Target Database Engine Edition : Microsoft SQL Server Standard Edition
    Target Database Engine Type : Standalone SQL Server
    */
    
    USE [msdb]
    
    GO
    
    /****** Object: Job [InsertRecords] Script Date: 7/2/2018 3:32:00 PM ******/
    
    BEGIN TRANSACTION
    
    DECLARE @ReturnCode INT
    
    SELECT @ReturnCode = 0
    
    /****** Object: JobCategory [[Uncategorized (Local)]] Script Date: 7/2/2018 3:32:00 PM ******/
    
    IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name=N'[Uncategorized (Local)]' AND category_class=1)
    
    BEGIN
    
    EXEC @ReturnCode = msdb.dbo.sp_add_category @class=N'JOB', @type=N'LOCAL', @name=N'[Uncategorized (Local)]'
    
    IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
    
    END
    
    DECLARE @jobId BINARY(16)
    
    EXEC @ReturnCode = msdb.dbo.sp_add_job @job_name=N'InsertRecords', @enabled=1,
    
    @notify_level_eventlog=0,
    
    @notify_level_email=0,
    
    @notify_level_netsend=0,
    
    @notify_level_page=0,
    
    @delete_level=0,
    
    @description=N'No description available.',
    
    @category_name=N'[Uncategorized (Local)]',
    
    @owner_login_name=N'kairos\kigiri', @job_id = @jobId OUTPUT
    
    IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
    
    /****** Object: Step [InsertRecords] Script Date: 7/2/2018 3:32:00 PM ******/
    
    EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @[email protected],
    
    @step_name=N'InsertRecords',
    
    @step_id=1,
    
    @cmdexec_success_code=0,
    
    @on_success_action=1,
    
    @on_success_step_id=0,
    
    @on_fail_action=2,
    
    @on_fail_step_id=0,
    
    @retry_attempts=0,
    
    @retry_interval=0,
    
    @os_run_priority=0, @subsystem=N'TSQL',
    
    @command=N'use BranchDB
    
    go
    
    insert into
    
    log_ship_tracker
    
    values
    
    (db_name(),getdate(),@@servername)
    
    
    
    use CorporateDB
    
    go
    
    insert into
    
    log_ship_tracker
    
    values
    
    (db_name(),getdate(),@@servername)
    
    GO',
    
    @database_name=N'master',
    
    @flags=0
    
    IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
    
    EXEC @ReturnCode = msdb.dbo.sp_update_job @job_id = @jobId, @start_step_id = 1 IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
    
    EXEC @ReturnCode = msdb.dbo.sp_add_jobschedule @[email protected], @name=N'Schedule', @enabled=1,
    
    @freq_type=4,
    
    @freq_interval=1,
    
    @freq_subday_type=4,
    
    @freq_subday_interval=1,
    
    @freq_relative_interval=0,
    
    @freq_recurrence_factor=0,
    
    @active_start_date=20180702,
    
    @active_end_date=99991231,
    
    @active_start_time=0,
    
    @active_end_time=235959,
    
    @schedule_uid=N'03e5f1b2-2e0b-4b30-8d60-3643c84aa08d' IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
    
    EXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @jobId, @server_name = N'(local)'
    
    IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
    
    COMMIT TRANSACTION
    
    GOTO EndSave
    
    QuitWithRollback:
    
    IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION
    
    EndSave:
    
    GO

    プライマリデータベースのテーブルをそれぞれクエリすると、(RecordTime列を使用して)BranchDBとCorporateDBの行が一致することを確認できます。同様に、セカンダリデータベースのテーブルを調べると、BranchDBとCorporateDBの間に30分のギャップがあることがはっきりとわかります。

    リスト4–ログトラッカーテーブルのクエリ

    select top 10 @@servername [Current_Server],* from BranchDB.dbo.log_ship_tracker order by RecordTime desc
    
    select top 10 @@servername [Current_Server], * from CorporateDB.dbo.log_ship_tracker order by RecordTime desc

    図。 9つのログトラッカーテーブルがプライマリデータベースで一致する

    図10個のログトラッカーテーブルには、セカンダリデータベースで最大30分のギャップがあります

    ユーザーエラーからの回復

    次に、この遅延の主な利点について説明しましょう。ユーザーが誤ってテーブルを削除したシナリオでは、遅延期間が経過していない限り、セカンダリデータベースからデータをすばやく回復できます。この例では、テーブルSales.Orderlinesを両方のデータベースにドロップし、テーブルが両方のデータベースに存在しないことを確認します。

    リスト5–オーダーラインテーブルの削除

    drop table BranchDB.Sales.Orderlines
    
    drop table CorporateDB.Sales.Orderlines
    
    GO
    
    
    
    use BranchDB
    
    go
    
    select
    
    @@servername [Current_Server]
    
    , db_name() [Database_Name]
    
    , name
    
    , schema_name(schema_id) [schema]
    
    , type_desc
    
    , create_date
    
    , modify_date
    
    from sys.tables where name='Orderlines'
    
    GO
    
    
    
    use CorporateDB
    
    go
    
    select
    
    @@servername [Current_Server]
    
    , db_name() [Database_Name]
    
    , name
    
    , schema_name(schema_id) [schema]
    
    , type_desc
    
    , create_date
    
    , modify_date
    
    from sys.tables where name='Orderlines'
    
    GO

    図。 11ドロップテーブルSales.Orderlines

    セカンダリサーバーでテーブルを探すと、両方のデータベースでテーブルがまだ使用可能であることがわかります。したがって、CorporateDBの場合、データを回復するのに5分もかかりません。 (図12)。ただし、次の復元サイクルが実行されると、CorporateDBデータベースのテーブルが失われます。このテーブルをリカバリするには、別の環境で完全バックアップを使用してポイントインタイムリカバリを実行してから、この特定のテーブルを抽出する必要があります。あなたはそれが少し時間がかかることに同意するでしょう。 BranchDB Orderlinesテーブルの場合、もう少し時間があり、リンクサーバーを介した単一のSQLステートメントでテーブルを回復できます(リスト6を参照)。

    図。 12 5分間のカウントダウン:両方のセカンダリデータベースにテーブルが存在します

    図。 13BranchDBテーブルを回復するための追加の25分

    リスト6–オーダーラインテーブルの回復

    USE [master]
    
    GO
    
    /****** Object: LinkedServer [10.2.1.84] Script Date: 7/2/2018 4:14:59 PM ******/
    
    EXEC master.dbo.sp_addlinkedserver @server = N'10.2.1.84', @srvproduct=N'SQL Server'
    
    /* For security reasons the linked server remote logins password is changed with ######## */
    
    EXEC master.dbo.sp_addlinkedsrvlogin
    
    @rmtsrvname=N'10.2.1.84',@useself=N'True',@locallogin=NULL,@rmtuser=NULL,@rmtpasswo rd=NULL
    
    GO
    
    select * into BranchDB.Sales.Orderlines from [10.2.1.84].BranchDB.Sales.Orderlines

    図。 14BranchDBSales.Orderlinesテーブルを回復します

    次に、プライマリサーバー(BranchDBデータベース)でテーブルが復元されたことを確認します。

    図。 15BranchDBSales.Orderlinesテーブルを回復します

    結論

    SQL Serverは、ディスク障害、破損、ユーザーエラーなど、さまざまな根本原因によるデータ損失から回復するためのさまざまな方法を提供します。バックアップからのポイントインタイム回復は、おそらくこれらの方法の中で最もよく知られています。ユーザーエラーの特定の単純なケース、または1つまたは2つのオブジェクトが失われる同様のケースでは、遅延回復を伴うトランザクションログ配布の使用を検討することをお勧めします。ただし、DRのニーズに厳密に合わせて構成されたセカンダリデータベースは、RPOが低い場合に選択する必要があることに注意してください。


    1. 2017年4月1日から2日までオーストリアのウィーンで開催されたMicrosoftAccessDevCon

    2. MySQLで重複する行を削除する

    3. ORA-00972識別子が長すぎますエイリアス列名

    4. エラー2003(HY000):「127.0.0.1」のMySQLサーバーに接続できません(111)