はじめに
トランザクションログ配布は、ディザスタリカバリサイトでライブデータベースのコピーを維持するために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が低い場合に選択する必要があることに注意してください。