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

インスタンス間でのバックアップの監視

    はじめに

    過去2、3か月の間に、企業全体の複数のSQLServerインスタンスのバックアップレポートを統合するSQLServerネイティブのソリューションを2回求められました。この質問は、必ずしもツールの購入にお金をかけたくないが、SQLServerの機能を活用する傾向がある友人から寄せられました。これを達成するための2つの可能な方法について考えました:

    1. リンクサーバー、カタログビュー、SQLエージェントジョブおよびデータベースメールの使用
    2. 中央管理サーバーの使用

    この記事では、最初の部分を示し、後で記事の2番目の部分があることを願っています。

    シナリオ

    私の環境は、AWSの別々のサーバーにある3つのインスタンスのセットで構成されています。これらの「サーバー」は、実際にはSQL Server 2017RTMCU5を実行しているAmazonEC2です。また、Amazon SimpleEmailServiceを利用してデータベースメールを構成します。本番環境では、オンプレミスの電子メールサーバーを確実に使用して、同じ目標を達成できます。この記事の後半で、ホスト名(したがってインスタンス名)が同じであることに気付くでしょう。これは、サーバーが同じAmazonマシンイメージからクローン化されたためです(「怠惰」はご容赦ください)。これは、本番環境では当てはまらない可能性があります。

    いくつかのバックアップを取る

    これらの3つのインスタンスにあるデータベースのバックアップをいくつか作成することから始めましょう。これにより、処理するデータが生成されます。次に、バックアップがシステムテーブル msdb.dbo.backupsetにキャプチャされていることを確認します。 およびmsdb.dbo.backupmediafamily 。これらの表の完全な説明は、このMicrosoftドキュメントで確認するか、 sp_columnsを使用するだけです。 。

    -- Listing 1: Taking Backups on the Instances
    -- Backup a single DB with one stripe
    backup database newdb to disk='newdb.bak'
    
    -- Backup all DBs in the instance with timestamp in the backupset name
    exec sp_MSforeachdb @command1=
    'declare @path varchar(300)
    set  @path=''M:\MSSQL\BACKUP\?_Backup'' + convert(varchar(10),getdate(),110) + ''.bak''
    print @path
    backup database [?] to [email protected]'
    
    -- Backup a single large DB with four stripes
    backup database [PieceMealDB] to
    disk='M:\MSSQL\BACKUP\PieceMealDB_01.bak',
    disk='M:\MSSQL\BACKUP\PieceMealDB_02.bak',
    disk='M:\MSSQL\BACKUP\PieceMealDB_03.bak',
    disk='M:\MSSQL\BACKUP\PieceMealDB_04.bak'
    with
    stats=10

    図3.msdb.dbo.backupsetの説明

    バックアップの確認

    次のスクリプトは、2つのカタログビューbackupsetと backupmediafamily を利用しています。 SQLServerのインスタンスで作成されたバックアップの履歴を調べるため。バックアップセットカタログには、各バックアップセットの行が含まれています。バックアップセットは、メディアセットに追加されるバックアップ操作の内容として定義されます。メディアセットは、1つ以上のバックアップ操作が書き込まれたメディアの注文コレクションです。

    -- Listing 2: Check Backups using msdb tables --
    PRINT 'Checking Databases Successfully Backed Up'
    use msdb
    go
    select bus.database_name,bus.type, case bus.type when 'D' then 'Full' when 'I' then 'Differential' when 'L' then 'Log' end backup_type, bus.backup_start_date, bus.backup_finish_date,
    (((DATEPART(HH,bus.backup_finish_date))- (DATEPART(HH,bus.backup_start_date)))*3600) +
    (((DATEPART(MI,bus.backup_finish_date)) - (DATEPART(MI,bus.backup_start_date)))*60) +
    (((DATEPART(SS,bus.backup_finish_date)) - DATEPART(SS,bus.backup_start_date)))
    [backup_time (secs)], bus.backup_size,
    bmf.physical_device_name 
    from backupset bus
    join backupmediafamily bmf on bus.media_set_id=bmf.media_set_id
    where bus.backup_start_date >= (getdate() - 7)
    order by bus.backup_start_date desc

    図5.バックアップチェックの出力例

    他のインスタンスのバックアップを確認する

    リンクサーバーを使用すると、リモートインスタンスからデータを抽出できます。この場合、単純なリンクサーバーを使用して、2つのリモートインスタンスのmsdbデータベースからバックアップ履歴情報を抽出します。これらのリンクサーバーのセキュリティ構成は完全にあなた次第ですが、私たちがここで維持しているのは、私たちの目的のために非常に単純です。リスト3は、これらのリンクサーバーを利用してバックアップ履歴データを集約できるスクリプトを示しています。

    図6.単純なリンクサーバー

    図7.2つのリモートインスタンスのリンクサーバー

    -- Listing 3: Checking Backups using msdb tables across Linked Servers
    use msdb
    go
    
    with srva as (
    select bus.server_name instance, bus.database_name,bus.type, 
    case bus.type when 'D' then 'Full' 
    when 'I' then 'Differential' 
    when 'L' then 'Log' end backup_type
    , bus.backup_start_date, bus.backup_finish_date,
    (((DATEPART(HH,bus.backup_finish_date))- (DATEPART(HH,bus.backup_start_date)))*3600) +
    (((DATEPART(MI,bus.backup_finish_date)) - (DATEPART(MI,bus.backup_start_date)))*60) +
    (((DATEPART(SS,bus.backup_finish_date)) - DATEPART(SS,bus.backup_start_date)))
    [backup_time (secs)], bus.backup_size,
    bmf.physical_device_name 
    from backupset bus
    join backupmediafamily bmf on bus.media_set_id=bmf.media_set_id
    where bus.backup_start_date >= (getdate() - 3)
    )
    
    , srvb as (
    select bus.server_name instance, bus.database_name,bus.type, 
    case bus.type when 'D' then 'Full' 
    when 'I' then 'Differential' 
    when 'L' then 'Log' end backup_type
    , bus.backup_start_date, bus.backup_finish_date,
    (((DATEPART(HH,bus.backup_finish_date))- (DATEPART(HH,bus.backup_start_date)))*3600) +
    (((DATEPART(MI,bus.backup_finish_date)) - (DATEPART(MI,bus.backup_start_date)))*60) +
    (((DATEPART(SS,bus.backup_finish_date)) - DATEPART(SS,bus.backup_start_date)))
    [backup_time (secs)], bus.backup_size,
    bmf.physical_device_name 
    from [10.0.1.155].msdb.dbo.backupset bus
    join [10.0.1.155].msdb.dbo.backupmediafamily bmf on bus.media_set_id=bmf.media_set_id
    where bus.backup_start_date >= (getdate() - 3)
    )
    , srvc as (
    select bus.server_name instance, bus.database_name,bus.type, 
    case bus.type when 'D' then 'Full' 
    when 'I' then 'Differential' 
    when 'L' then 'Log' end backup_type
    , bus.backup_start_date, bus.backup_finish_date,
    (((DATEPART(HH,bus.backup_finish_date))- (DATEPART(HH,bus.backup_start_date)))*3600) +
    (((DATEPART(MI,bus.backup_finish_date)) - (DATEPART(MI,bus.backup_start_date)))*60) +
    (((DATEPART(SS,bus.backup_finish_date)) - DATEPART(SS,bus.backup_start_date)))
    [backup_time (secs)], bus.backup_size,
    bmf.physical_device_name 
    from [10.0.1.83].msdb.dbo.backupset bus
    join [10.0.1.83].msdb.dbo.backupmediafamily bmf on bus.media_set_id=bmf.media_set_id
    where bus.backup_start_date >= (getdate() - 3)
    )
    
    select * from srva
    union 
    select * from srvb
    union
    select * from srvc;

    SESとデータベースメールの組み込み

    次のステップは、このチェックを自動化し、結果セットをデータベース管理者にメールで送信することです。必要な手順の概要は次のとおりです。

      1. AmazonSESを設定する 。 Amazon SESクイックスタートで提供されているドキュメントを使用して、AWSでメールをすばやく設定する方法を学ぶことができます。オンプレミスの電子メールサービスを使用する場合、これはDBAには必要ありません。
      2. データベースメールの構成 。この記事はデータベースメールのデモンストレーションを目的としたものではないため、SQLメールアカウント構成のスクリーンショットを示します。

        図7.SQLメールアカウントの設定

        • SESを使用してメールを送信するときのポート番号は25ではなく587です
        • Amazon SESには安全な接続が必要であるため、ライラックで識別されるチェックボックス(図7)を選択する必要があります
        • SMTP認証情報を使用した基本認証が必要です(つまり、匿名認証は許可されていません)。

        データベースメールにAmazonSESを使用する場合は、次の点に注意する必要があります。

      3. メールプロファイルを使用するようにSQLエージェントを構成する 。 SQL Serverエージェントは、データベースメールの構成中に作成されたメールプロファイルを使用して、エージェントジョブが電子メールを送信するように構成する必要があります。 (図8を参照)
      4. ステージングテーブルを作成する 。ステージングテーブルには、リンクサーバーを使用してターゲットにしたインスタンスからのすべてのバックアップ履歴データの集計結果セットが含まれます。テーブルDDLをリスト4に示します。
    -- Listing 4: Backup History Table DDL
    SET ANSI_NULLS ON
    GO
    
    SET QUOTED_IDENTIFIER ON
    GO
    
    CREATE TABLE [dbo].[backuphistory](
    	[instance] [nvarchar](128) NULL,
    	[database_name] [nvarchar](128) NULL,
    	[type] [char](1) NULL,
    	[backup_type] [varchar](12) NULL,
    	[backup_start_date] [datetime] NULL,
    	[backup_finish_date] [datetime] NULL,
    	[backup_time (secs)] [int] NULL,
    	[backup_size] [numeric](20, 0) NULL,
    	[physical_device_name] [nvarchar](260) NULL
    ) ON [PRIMARY]
    GO

    図8.SQLエージェントの設定

    先に進み、SQLエージェントジョブのリスト3のスクリプトをスケジュールします。リスト5に完全なスクリプトがあります。

    -- Listing 5: Complete SQL Agent Job for Backup History Notification
    
    USE [msdb]
    GO
    
    /****** Object:  Job [Enteprise Backup History Summary]    Script Date: 9/26/2018 10:16:46 PM ******/
    BEGIN TRANSACTION
    DECLARE @ReturnCode INT
    SELECT @ReturnCode = 0
    /****** Object:  JobCategory [[Uncategorized (Local)]]    Script Date: 9/26/2018 10:16:46 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'Enteprise Backup History Summary', 
    		@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'TWENTYTOWERS\Administrator', @job_id = @jobId OUTPUT
    IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
    /****** Object:  Step [Aggregate Backup History]    Script Date: 9/26/2018 10:16:46 PM ******/
    EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @[email protected], @step_name=N'Aggregate Backup History', 
    		@step_id=1, 
    		@cmdexec_success_code=0, 
    		@on_success_action=3, 
    		@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'-- Check Backups using msdb tables --
    -- Across Linked Servers
    use msdb
    go
    
    truncate table [msdb].[dbo].[backuphistory];
    
    with srva as (
    select bus.server_name instance, bus.database_name,bus.type, 
    case bus.type when ''D'' then ''Full'' 
    when ''I'' then ''Differential'' 
    when ''L'' then ''Log'' end backup_type
    , bus.backup_start_date, bus.backup_finish_date,
    (((DATEPART(HH,bus.backup_finish_date))- (DATEPART(HH,bus.backup_start_date)))*3600) +
    (((DATEPART(MI,bus.backup_finish_date)) - (DATEPART(MI,bus.backup_start_date)))*60) +
    (((DATEPART(SS,bus.backup_finish_date)) - DATEPART(SS,bus.backup_start_date)))
    [backup_time (secs)], bus.backup_size,
    bmf.physical_device_name 
    from backupset bus
    join backupmediafamily bmf on bus.media_set_id=bmf.media_set_id
    where bus.backup_start_date >= (getdate() - 3)
    )
    
    , srvb as (
    select bus.server_name instance, bus.database_name,bus.type, 
    case bus.type when ''D'' then ''Full'' 
    when ''I'' then ''Differential'' 
    when ''L'' then ''Log'' end backup_type
    , bus.backup_start_date, bus.backup_finish_date,
    (((DATEPART(HH,bus.backup_finish_date))- (DATEPART(HH,bus.backup_start_date)))*3600) +
    (((DATEPART(MI,bus.backup_finish_date)) - (DATEPART(MI,bus.backup_start_date)))*60) +
    (((DATEPART(SS,bus.backup_finish_date)) - DATEPART(SS,bus.backup_start_date)))
    [backup_time (secs)], bus.backup_size,
    bmf.physical_device_name 
    from [10.0.1.155].msdb.dbo.backupset bus
    join [10.0.1.155].msdb.dbo.backupmediafamily bmf on bus.media_set_id=bmf.media_set_id
    where bus.backup_start_date >= (getdate() - 3)
    )
    , srvc as (
    select bus.server_name instance, bus.database_name,bus.type, 
    case bus.type when ''D'' then ''Full'' 
    when ''I'' then ''Differential'' 
    when ''L'' then ''Log'' end backup_type
    , bus.backup_start_date, bus.backup_finish_date,
    (((DATEPART(HH,bus.backup_finish_date))- (DATEPART(HH,bus.backup_start_date)))*3600) +
    (((DATEPART(MI,bus.backup_finish_date)) - (DATEPART(MI,bus.backup_start_date)))*60) +
    (((DATEPART(SS,bus.backup_finish_date)) - DATEPART(SS,bus.backup_start_date)))
    [backup_time (secs)], bus.backup_size,
    bmf.physical_device_name 
    from [10.0.1.83].msdb.dbo.backupset bus
    join [10.0.1.83].msdb.dbo.backupmediafamily bmf on bus.media_set_id=bmf.media_set_id
    where bus.backup_start_date >= (getdate() - 3)
    )
    
    insert into [msdb].[dbo].[backuphistory]
    select * from srva
    union 
    select * from srvb
    union
    select * from srvc;
    ', 
    		@database_name=N'msdb', 
    		@flags=0
    IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
    /****** Object:  Step [Query Member Servers for Backups]    Script Date: 9/26/2018 10:16:46 PM ******/
    EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @[email protected], @step_name=N'Query Member Servers for Backups', 
    		@step_id=2, 
    		@cmdexec_success_code=0, 
    		@on_success_action=3, 
    		@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'DECLARE @tableHTML  NVARCHAR(MAX) ;
    
    SET @tableHTML =
        N''<H1><font face="Verdana" size="4">Enterprise Backup History Summary</H1>'' +
        N''<table border="1"><font face="Verdana" size="2">'' +
        N''<tr><th><font face="Verdana" size="2">Instance Name</th>'' +
    	N''<th><font face="Verdana" size="2">Database Name</th>'' +
        N''<th><font face="Verdana" size="2">Backup Start Date</th>'' +
        N''<th><font face="Verdana" size="2">Backup Finish Date</th>'' +
    	N''<th><font face="Verdana" size="2">Backup Time (secs)</th>'' +
        N''<th><font face="Verdana" size="2">Backup Size</th>'' +
        N''<th><font face="Verdana" size="2">Physical Device Name</th></tr>'' +
        CAST ( ( SELECT td = bus.instance,			'''',
    					td = bus.database_name,       '''',
                        td = bus.backup_start_date, '''',
                        td = bus.backup_finish_date, '''',
                        td = (((DATEPART(HH,bus.backup_finish_date))- (DATEPART(HH,bus.backup_start_date)))*3600) +
    (((DATEPART(MI,bus.backup_finish_date)) - (DATEPART(MI,bus.backup_start_date)))*60) +
    (((DATEPART(SS,bus.backup_finish_date)) - DATEPART(SS,bus.backup_start_date))), '''',
                        td = bus.backup_size, '''',
                        td = bus.physical_device_name
                  FROM backuphistory as bus
                  WHERE bus.backup_start_date >= (getdate() - 7)
                  ORDER BY bus.backup_start_date desc
                  FOR XML PATH(''tr''), TYPE 
        ) AS NVARCHAR(MAX) ) +
        N''</table>'' + 	''<p style="margin-top: 0; margin-bottom: 0">&nbsp;</p>
    	<p style="margin-top: 0; margin-bottom: 0"><font face="Verdana" size="2">Thanks   
    	and Regards,</font></p>  &nbsp;
    	<p style="margin-top: 0; margin-bottom: 0"><font face="Verdana" size="2">Enterprise Database Operations</font></p>  
    	<p>&nbsp;</p>''  ;
    
    EXEC msdb.dbo.sp_send_dbmail @recipients=''[email protected];[email protected]'',
        @subject = ''Enterprise Backup History Summary'',
        @body = @tableHTML ,
        @body_format = ''HTML'' ;', 
    		@database_name=N'msdb', 
    		@flags=0
    IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
    /****** Object:  Step [Mail Complete Result Set to Support]    Script Date: 9/26/2018 10:16:46 PM ******/
    EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @[email protected], @step_name=N'Mail Complete Result Set to Support', 
    		@step_id=3, 
    		@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'DECLARE @tableHTML  NVARCHAR(MAX) ;
    
    SET @tableHTML =
        N''<H1><font face="Verdana" size="4">Enterprise Backup History Summary</H1>'' +
        N''<table border="1"><font face="Verdana" size="2">'' +
        N''<tr><th><font face="Verdana" size="2">Instance Name</th>'' +
    	N''<th><font face="Verdana" size="2">Database Name</th>'' +
        N''<th><font face="Verdana" size="2">Backup Start Date</th>'' +
        N''<th><font face="Verdana" size="2">Backup Finish Date</th>'' +
    	N''<th><font face="Verdana" size="2">Backup Time (secs)</th>'' +
        N''<th><font face="Verdana" size="2">Backup Size</th>'' +
        N''<th><font face="Verdana" size="2">Physical Device Name</th></tr>'' +
        CAST ( ( SELECT td = bus.instance,			'''',
    					td = bus.database_name,       '''',
                        td = bus.backup_start_date, '''',
                        td = bus.backup_finish_date, '''',
                        td = (((DATEPART(HH,bus.backup_finish_date))- (DATEPART(HH,bus.backup_start_date)))*3600) +
    (((DATEPART(MI,bus.backup_finish_date)) - (DATEPART(MI,bus.backup_start_date)))*60) +
    (((DATEPART(SS,bus.backup_finish_date)) - DATEPART(SS,bus.backup_start_date))), '''',
                        td = bus.backup_size, '''',
                        td = bus.physical_device_name
                  FROM backuphistory as bus
                  WHERE bus.backup_start_date >= (getdate() - 7)
                  ORDER BY bus.backup_start_date desc
                  FOR XML PATH(''tr''), TYPE 
        ) AS NVARCHAR(MAX) ) +
        N''</table>'' + 	''<p style="margin-top: 0; margin-bottom: 0">&nbsp;</p>
    	<p style="margin-top: 0; margin-bottom: 0"><font face="Verdana" size="2">Thanks   
    	and Regards,</font></p>  &nbsp;
    	<p style="margin-top: 0; margin-bottom: 0"><font face="Verdana" size="2">Enterprise Database Operations</font></p>  
    	<p>&nbsp;</p>''  ;
    
    EXEC msdb.dbo.sp_send_dbmail @recipients=''[email protected];[email protected]'',
        @subject = ''Enterprise Backup History Summary'',
        @body = @tableHTML ,
        @body_format = ''HTML'' ;', 
    		@database_name=N'msdb', 
    		@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_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

    このジョブを実行すると、図9に示す出力が得られます。テーブルは非常に単純なHTMLを使用して作成され、ニーズに合わせてさらに開発できます。

    図9.SQLエージェントジョブ実行の電子メール出力

    結論

    リンクサーバーを使用して、バックアップ履歴情報(およびシステムデータベースに含まれるその他のデータ)を集約する簡単な方法を実行しました。さらに、SQLエージェント、データベースメール、および小さなHTMLを使用して、このプロセスを自動化しました。この方法は少し粗雑に思えるかもしれませんし、もっとうまくいくツールがあると確信していますが、これはSQLServerや低予算の環境を始めたばかりの人にとってはサーバーの目的になります。少しの創造性で、スクリプトをさらにカスタマイズし、スクリプトを他の用途に適合させることができます。

    参照

    1. データベースメールの設定
    2. AmazonSESの使用を開始する
    3. リンクサーバー
    4. バックアップ履歴とヘッダー情報

    1. OracleRACとシーケンス

    2. DBMS_OUTPUT.Get_Linesを使用して、DBMS_OUTPUT.Put_Line出力をOracleのテーブルに記録します。

    3. Windows上のODBCアプリケーションをZohoCRMに接続します

    4. Simple Encrypted Arithmetic Library(SEAL)とseal::Ciphertext変数