web-dev-qa-db-ja.com

Ola Hallengren 'SQL Server Maintenance Solution'のインストール/実行の自動化に関する問題

私はできる限りこのことを説明するために最善を尽くしますが、私はDBAではないので、親切に我慢してください。新しいサーバー上のエンドユーザークライアント向けにSQL Serverを継続的に展開する必要があります。私は、すべてのバックアップおよびメンテナンスエージェントジョブ(スケジュールと必要な設定で事前に構成されています)の実装を含め、これを自動化するPowerShellスクリプトを持っています。主にSQL WEBエディションで作業しているため、メンテナンスパッケージをインポートするオプションがないため、回避策として、事前構成されたジョブをエクスポートし、展開の一部として* .sqlファイルとしてインポートしました。この1つのPowerShellスクリプトは、SQL Server 2012、2014、2016、2017のプロビジョニングを処理します(クライアントの要求に応じて異なります)。

私の特定の問題は、使用するドライブ文字とSQL Serverのバージョンが異なるため、使用するSQL Serverのルートフォルダーが一貫していないため、@BackupDirectoryディレクトリ変数に依存するジョブが機能しないこれはサーバーごとに変わる可能性があるためです。私が達成しようとしているのは、メンテナンスジョブ内の実行時にインストールパスに基づいて@BackupDirectory変数を動的に設定することです。部分的にしか機能していません。

インストールパスを取得するために、次のようなものを使用しています(他の検索から借用/変更)。

declare @rc int, @dir nvarchar(4000) 
DECLARE @BackupPath nvarchar(max)

exec @rc = master.dbo.xp_instance_regread
      N'HKEY_LOCAL_MACHINE',
      N'Software\Microsoft\MSSQLServer\Setup',
      N'SQLPath', 
      @dir output, 'no_output'

set @BackupPath = @dir+'\Backup'

これは次のようなものを返します:

F:\Microsoft SQL Server\MSSQL14.MSSQLSERVER\MSSQL\Backup

これと同じロジックをDatabaseBackup - USER_DATABASES - FULLという名前のSQL Serverエージェントジョブに追加しようとしていますが、実行中の問題は、このコマンド内で変数を呼び出す方法がわからないことです。

@command=N'sqlcmd -E -S $(ESCAPE_SQUOTE(SRVR)) -d master -Q "EXECUTE [dbo].[DatabaseBackup] @Databases = ''SYSTEM_DATABASES,USER_DATABASES'', @Directory = N''F:\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\Backup'', @BackupType = ''FULL'', @Verify = ''Y'', @CleanupTime = 120, @CheckSum = ''Y'', @LogToTable = ''Y''" -b',  

@Directory =の変数と同じ@BackupPathが必要です。このような単純なことを試みると、次のエラーが発生します。

スカラー変数@BackupPathを宣言する必要があります

@command=N'sqlcmd -E -S $(ESCAPE_SQUOTE(SRVR)) -d master -Q "EXECUTE [dbo].[DatabaseBackup] @Databases = ''SYSTEM_DATABASES,USER_DATABASES'', @Directory = @BackupPath, @BackupType = ''FULL'', @Verify = ''Y'', @CleanupTime = 120, @CheckSum = ''Y'', @LogToTable = ''Y''" -b', 

これを実行する方法が複雑で、より簡単な方法があるため、私は提案を受け入れることができますが、ここで私を導いた制約があります。残念ながら、私はT-SQLをよく知らないので、できる限りの検索と試行を行いましたが、行き詰まっていました。私たちの全体的な目標は、これらのインストールをできるだけ均一に保つことです。そのため、バックアップディレクトリを通常のルートディレクトリのインストールパス内に保持したいと考えています。

うまくいけば、私はこれを明確に説明しました!私はどんな助けと入力にも大いに感謝します。

追加情報

エージェントジョブの完全なT-SQLを追加して、変数を追加しようとしているのを除いて、それを確認できるようにします。メインスクリプトがジョブを作成するときに通常追加されるパスのみが表示されます。

USE [msdb]
GO

/* ********* Get Install Directory for Backup folder path ********* */

declare @rc int, @dir nvarchar(4000) 
DECLARE @BackupPath nvarchar(max)

exec @rc = master.dbo.xp_instance_regread
      N'HKEY_LOCAL_MACHINE',
      N'Software\Microsoft\MSSQLServer\Setup',
      N'SQLPath', 
      @dir output, 'no_output'
set @BackupPath = @dir+'\Backup'

/****** Object:  Job [DatabaseBackup - Daily FULL Backup]    Script Date: 3/5/2018 4:28:49 PM ******/
BEGIN TRANSACTION
DECLARE @ReturnCode INT
SELECT @ReturnCode = 0
/****** Object:  JobCategory [Database Maintenance]    Script Date: 3/5/2018 4:28:49 PM ******/
IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name=N'Database Maintenance' AND category_class=1)
BEGIN
EXEC @ReturnCode = msdb.dbo.sp_add_category @class=N'JOB', @type=N'LOCAL', @name=N'Database Maintenance'
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback

END

DECLARE @jobId BINARY(16)
EXEC @ReturnCode =  msdb.dbo.sp_add_job @job_name=N'DatabaseBackup - Daily FULL Backup', 
        @enabled=1, 
        @notify_level_eventlog=2, 
        @notify_level_email=0, 
        @notify_level_netsend=0, 
        @notify_level_page=0, 
        @delete_level=0, 
        @description=N'Source: https://ola.hallengren.com', 
        @category_name=N'Database Maintenance', 
        @owner_login_name=N'NT SERVICE\SQLSERVERAGENT', @job_id = @jobId OUTPUT
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
/****** Object:  Step [DatabaseBackup - ALL - FULL]    Script Date: 3/5/2018 4:28:49 PM ******/
EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N'DatabaseBackup - ALL - FULL', 
        @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'CmdExec', 
        @command=N'sqlcmd -E -S $(ESCAPE_SQUOTE(SRVR)) -d master -Q "EXECUTE [dbo].[DatabaseBackup] @Databases = ''SYSTEM_DATABASES,USER_DATABASES'', @Directory = N''F:\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\Backup'', @BackupType = ''FULL'', @Verify = ''Y'', @CleanupTime = 120, @CheckSum = ''Y'', @LogToTable = ''Y''" -b', 
        @output_file_name=N'$(ESCAPE_SQUOTE(SQLLOGDIR))\DatabaseBackup_$(ESCAPE_SQUOTE(JOBID))_$(ESCAPE_SQUOTE(STEPID))_$(ESCAPE_SQUOTE(STRTDT))_$(ESCAPE_SQUOTE(STRTTM)).txt', 
        @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 @job_id=@jobId, @name=N'Daily Full Backup', 
        @enabled=1, 
        @freq_type=4, 
        @freq_interval=1, 
        @freq_subday_type=1, 
        @freq_subday_interval=0, 
        @freq_relative_interval=0, 
        @freq_recurrence_factor=0, 
        @active_start_date=20180305, 
        @active_end_date=99991231, 
        @active_start_time=50000, 
        @active_end_time=235959, 
        @schedule_uid=N'169d88c5-5d47-439b-b576-389e9395b9c6'
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

その他の考慮事項

それについて考えると、PSを使用してレジストリにクエリを実行し、このジョブの.sql入力ファイルを変更することで、SQL Serverの外部でこれを実行できる回避策があります。 SQL Server内だけで実行できるかどうかを確認し、SQL Serverから学びたいと思います。

2
Wayne

その方法でSQLエージェントステップに変数を渡すことは、変数自体を知らないことを考えると不可能です。 T-SQLの変数は、使用する前に定義/宣言する必要があります...そのため、宣言されていないというエラーが発生します。あなたのさらなる検討は、実際にはPowerShellでそれを行う適切な方法です。 PowerShellを介してその値を検索し、それをSQLエージェントジョブのT-SQL定義に挿入します。

さて、私が注意する代替案は(日常のDBAではない人々を中心に構築されているため) dbatools PowerShell module には「Ola対応」のコマンドが含まれています。完全なOlaメンテナンスソリューションを展開するために使用できるコマンドがあります。

Install-DbaMaintenanceSolutionを使用してジョブをデプロイします。これには、クリーンアップ時間、バックアップディレクトリなどをカスタマイズできるいくつかのパラメーターが含まれています。

他のいくつかのコマンドを利用して、必要に応じて、またはサーバーのグループに基づいて、ジョブスケジュール(Set-DbaAgentSchedule)を操作することもできます。

SMOはモジュール内でより簡単にアクセスできるので、取得はバックアップディレクトリまたはルートインスタンスディレクトリのように考えることができます:

Import-Module dbatools
$server = Connect-DbaInstance -SqlInstance MyServer
# Grab the default backup directory (if it is set)
$server.BackupDirectory
# Grab the root directory of the instance
$server.RootDirectory
2
user507