サーバーとデータベースのオプションに取り組む際に、データベースを正常に保つためのプロアクティブなタスクについての説明は、この投稿でも継続されます。あなたはすでにこれが簡単な投稿になると思っているかもしれません-誰がサーバーやデータベースのオプションを頻繁に変更しますか?特にSQLServerにアクセスできる人がたくさんいる場合は、驚くでしょう。サーバーとデータベースのオプションはめったに変更されないはずです。ほとんどの場合、これらはインストール時に設定され、そのままになります。ただし、パフォーマンスに関連する場合でも、アプリケーションコードの変更が原因である場合でも、最初に何かが正しく設定されていない場合でも、変更を加えるのには十分な理由があります。最初にこれらの変更をテストし、変更の前後に適切なメトリックをキャプチャします。それはかなり簡単で明白なようですよね?そう思うかもしれませんが、厳密に守られている変更管理プロセスがない場合は、そうではありません。
ほとんどの環境では、複数の人がSQL Serverにアクセスでき、複数の人がサーバーまたはデータベースのオプションを変更するために必要な権限を持っています。間違った設定を変更すると、パフォーマンスに大きな影響を与える可能性があります。 (誤って最大メモリ設定をMBではなくGBの値に設定したことがありますか?疑問に思われる場合は、SQLServerインスタンスを起動するために必要なメモリが128MBではありません。これを修正する方法についてはTedKruegerの投稿を確認してください。 、間違いを犯した場合に備えてください。)他の変更により、小さな問題が発生する可能性がありますが、それでも問題があり、追跡が難しい場合があります(統計の自動作成を無効にするのが良い例です)。これらの変更は、十分に伝達されている(時々、忘れてしまった火を消すのに忙しい)か、気づきやすい(常にではない)と思うかもしれません。これを回避するために、設定を追跡し、定期的なチェックを実行するとき(または問題のトラブルシューティングを行うとき)に、何も変更されていないことを確認します。
データのキャプチャ
気になるデータを保持するためにmsdbに依存していたメンテナンスタスクに関する以前の投稿とは異なり、インスタンスとデータベースの設定のためにデータキャプチャを設定する必要があります。 sys.configurationsとsys.database_infoをベースラインデータベースのテーブルに毎日スナップショットし、クエリを使用して何かが変更されたかどうか、いつ変更されたかを確認します。
USE [Baselines]; GO IF OBJECT_ID(N'dbo.SQLskills_ConfigData', N'U') IS NULL BEGIN CREATE TABLE [dbo].[SQLskills_ConfigData] ( [ConfigurationID] [int] NOT NULL , [Name] [nvarchar](35) NOT NULL , [Value] [sql_variant] NULL , [ValueInUse] [sql_variant] NULL , [CaptureDate] [datetime] NOT NULL DEFAULT SYSDATETIME() ) ON [PRIMARY]; GO CREATE CLUSTERED INDEX [CI_SQLskills_ConfigData] ON [dbo].[SQLskills_ConfigData] ([CaptureDate],[ConfigurationID]); GO IF OBJECT_ID(N'dbo.SQLskills_DBData', N'U') IS NULL BEGIN CREATE TABLE [dbo].[SQLskills_DBData] ( [name] [sysname] NOT NULL, [database_id] [int] NOT NULL, [source_database_id] [int] NULL, [owner_sid] [varbinary](85) NULL, [create_date] [datetime] NOT NULL, [compatibility_level] [tinyint] NOT NULL, [collation_name] [sysname] NULL, [user_access] [tinyint] NULL, [user_access_desc] [nvarchar](60) NULL, [is_read_only] [bit] NULL, [is_auto_close_on] [bit] NOT NULL, [is_auto_shrink_on] [bit] NULL, [state] [tinyint] NULL, [state_desc] [nvarchar](60) NULL, [is_in_standby] [bit] NULL, [is_cleanly_shutdown] [bit] NULL, [is_supplemental_logging_enabled] [bit] NULL, [snapshot_isolation_state] [tinyint] NULL, [snapshot_isolation_state_desc] [nvarchar](60) NULL, [is_read_committed_snapshot_on] [bit] NULL, [recovery_model] [tinyint] NULL, [recovery_model_desc] [nvarchar](60) NULL, [page_verify_option] [tinyint] NULL, [page_verify_option_desc] [nvarchar](60) NULL, [is_auto_create_stats_on] [bit] NULL, [is_auto_update_stats_on] [bit] NULL, [is_auto_update_stats_async_on] [bit] NULL, [is_ansi_null_default_on] [bit] NULL, [is_ansi_nulls_on] [bit] NULL, [is_ansi_padding_on] [bit] NULL, [is_ansi_warnings_on] [bit] NULL, [is_arithabort_on] [bit] NULL, [is_concat_null_yields_null_on] [bit] NULL, [is_numeric_roundabort_on] [bit] NULL, [is_quoted_identifier_on] [bit] NULL, [is_recursive_triggers_on] [bit] NULL, [is_cursor_close_on_commit_on] [bit] NULL, [is_local_cursor_default] [bit] NULL, [is_fulltext_enabled] [bit] NULL, [is_trustworthy_on] [bit] NULL, [is_db_chaining_on] [bit] NULL, [is_parameterization_forced] [bit] NULL, [is_master_key_encrypted_by_server] [bit] NOT NULL, [is_published] [bit] NOT NULL, [is_subscribed] [bit] NOT NULL, [is_merge_published] [bit] NOT NULL, [is_distributor] [bit] NOT NULL, [is_sync_with_backup] [bit] NOT NULL, [service_broker_guid] [uniqueidentifier] NOT NULL, [is_broker_enabled] [bit] NOT NULL, [log_reuse_wait] [tinyint] NULL, [log_reuse_wait_desc] [nvarchar](60) NULL, [is_date_correlation_on] [bit] NOT NULL, [is_cdc_enabled] [bit] NOT NULL, [is_encrypted] [bit] NULL, [is_honor_broker_priority_on] [bit] NULL, [replica_id] [uniqueidentifier] NULL, [group_database_id] [uniqueidentifier] NULL, [default_language_lcid] [smallint] NULL, [default_language_name] [nvarchar](128) NULL, [default_fulltext_language_lcid] [int] NULL, [default_fulltext_language_name] [nvarchar](128) NULL, [is_nested_triggers_on] [bit] NULL, [is_transform_noise_words_on] [bit] NULL, [two_digit_year_cutoff] [smallint] NULL, [containment] [tinyint] NULL, [containment_desc] [nvarchar](60) NULL, [target_recovery_time_in_seconds] [int] NULL, [CaptureDate] [datetime] NOT NULL DEFAULT SYSDATETIME() ) ON [PRIMARY]; GO CREATE CLUSTERED INDEX [CI_SQLskills_DBData] ON [dbo].[SQLskills_DBData] ([CaptureDate],[database_id]); GO
SQLskills_DBDataテーブルを作成するスクリプトは、SQL Server 2014と互換性があります。以前のバージョンでは、ベーステーブルとスナップショットクエリを変更する必要がある場合があります(次のコードセットを参照)。
テーブルを作成したら、次の2つのクエリを毎日実行するジョブを作成します。繰り返しになりますが、これらのオプションが1日に2回以上変更されることは期待できません。また、設定を変更してから元に戻すことはできないと思いますが(したがって、キャプチャには表示されません)、それは常に可能性があります。 。設定が頻繁または一時的に変更されるため、このデータキャプチャがニーズに合わない場合は、トリガーを実装するか、監査を使用することをお勧めします。
(sp_configure)を介してサーバーオプションを編集するには、ログインにALTER SETTINGSサーバーレベルのアクセス許可が必要です。これは、sysadminまたはserveradminロールのメンバーである場合に含まれます。ほとんどのデータベース設定(ALTER DATABASE SET)を編集するには、データベースでのALTER権限が必要ですが、CONTROLSERVERやサーバーレベルのオプションALTERANY DATABASEなど、一部のオプションには追加の権限が必要です。
/* Statements to use in scheduled job */ INSERT INTO [dbo].[SQLskills_ConfigData] ( [ConfigurationID] , [Name] , [Value] , [ValueInUse] ) SELECT [configuration_id] , [name] , [value] , [value_in_use] FROM [sys].[configurations]; GO INSERT INTO [dbo].[SQLskills_DBData] ( [name], [database_id], [source_database_id], [owner_sid], [create_date], [compatibility_level], [collation_name], [user_access], [user_access_desc], [is_read_only], [is_auto_close_on], [is_auto_shrink_on], [state], [state_desc], [is_in_standby], [is_cleanly_shutdown], [is_supplemental_logging_enabled], [snapshot_isolation_state], [snapshot_isolation_state_desc], [is_read_committed_snapshot_on], [recovery_model], [recovery_model_desc], [page_verify_option], [page_verify_option_desc], [is_auto_create_stats_on], [is_auto_update_stats_on], [is_auto_update_stats_async_on], [is_ansi_null_default_on], [is_ansi_nulls_on], [is_ansi_padding_on], [is_ansi_warnings_on], [is_arithabort_on], [is_concat_null_yields_null_on], [is_numeric_roundabort_on], [is_quoted_identifier_on], [is_recursive_triggers_on], [is_cursor_close_on_commit_on], [is_local_cursor_default], [is_fulltext_enabled], [is_trustworthy_on], [is_db_chaining_on], [is_parameterization_forced], [is_master_key_encrypted_by_server], [is_published], [is_subscribed], [is_merge_published], [is_distributor], [is_sync_with_backup], [service_broker_guid], [is_broker_enabled], [log_reuse_wait], [log_reuse_wait_desc], [is_date_correlation_on], [is_cdc_enabled], [is_encrypted], [is_honor_broker_priority_on], [replica_id], [group_database_id], [default_language_lcid], [default_language_name], [default_fulltext_language_lcid], [default_fulltext_language_name], [is_nested_triggers_on], [is_transform_noise_words_on], [two_digit_year_cutoff], [containment], [containment_desc], [target_recovery_time_in_seconds] ) SELECT [name], [database_id], [source_database_id], [owner_sid], [create_date], [compatibility_level], [collation_name], [user_access], [user_access_desc], [is_read_only], [is_auto_close_on], [is_auto_shrink_on], [state], [state_desc], [is_in_standby], [is_cleanly_shutdown], [is_supplemental_logging_enabled], [snapshot_isolation_state], [snapshot_isolation_state_desc], [is_read_committed_snapshot_on], [recovery_model], [recovery_model_desc], [page_verify_option], [page_verify_option_desc], [is_auto_create_stats_on], [is_auto_update_stats_on], [is_auto_update_stats_async_on], [is_ansi_null_default_on], [is_ansi_nulls_on], [is_ansi_padding_on], [is_ansi_warnings_on], [is_arithabort_on], [is_concat_null_yields_null_on], [is_numeric_roundabort_on], [is_quoted_identifier_on], [is_recursive_triggers_on], [is_cursor_close_on_commit_on], [is_local_cursor_default], [is_fulltext_enabled], [is_trustworthy_on], [is_db_chaining_on], [is_parameterization_forced], [is_master_key_encrypted_by_server], [is_published], [is_subscribed], [is_merge_published], [is_distributor], [is_sync_with_backup], [service_broker_guid], [is_broker_enabled], [log_reuse_wait], [log_reuse_wait_desc], [is_date_correlation_on], [is_cdc_enabled], [is_encrypted], [is_honor_broker_priority_on], [replica_id], [group_database_id], [default_language_lcid], [default_language_name], [default_fulltext_language_lcid], [default_fulltext_language_name], [is_nested_triggers_on], [is_transform_noise_words_on], [two_digit_year_cutoff], [containment], [containment_desc], [target_recovery_time_in_seconds] FROM [sys].[databases]; GO
変更の確認
この情報を取得したので、どのようにして変更を見つけますか?複数の設定が変更される可能性があることを知っていて、異なる日付で、各行を調べるメソッドが必要です。これを行うのは難しいことではありませんが、最も美しいコードは生成されません。サーバーオプションについては、それほど悪くはありません:
;WITH [f] AS ( SELECT ROW_NUMBER() OVER (PARTITION BY [ConfigurationID] ORDER BY [CaptureDate] ASC) AS [RowNumber], [ConfigurationID] AS [ConfigurationID], [Name] AS [Name], [Value] AS [Value], [ValueInUse] AS [ValueInUse], [CaptureDate] AS [CaptureDate] FROM [Baselines].[dbo].[ConfigData] ) SELECT [f].[Name] AS [Setting], [f].[CaptureDate] AS [Date], [f].[Value] AS [Previous Value], [f].[ValueInUse] AS [Previous Value In Use], [n].[CaptureDate] AS [Date Changed], [n].[Value] AS [New Value], [n].[ValueInUse] AS [New Value In Use] FROM [f] LEFT OUTER JOIN [f] AS [n] ON [f].[ConfigurationID] = [n].[ConfigurationID] AND [f].[RowNumber] + 1 = [n].[RowNumber] WHERE ([f].[Value] <> [n].[Value] OR [f].[ValueInUse] <> [n].[ValueInUse]); GO
データベースオプションの場合、クエリはストアドプロシージャ内にあり(扱いにくいため)、ここからダウンロードできます。ストアドプロシージャを実行するには:
EXEC dbo.usp_FindDBSettingChanges
出力には、データベースと変更された設定、および日付が一覧表示されます。
パフォーマンスの問題が発生したときにこれらのクエリを実行して、設定が変更されたかどうかをすばやく確認できます。または、もう少しプロアクティブになって、何かが変更された場合に通知するスケジュールされたジョブで定期的に実行することもできます。変更があった場合にデータベースメールを使用してメールを送信するためのT-SQLコードを含めませんでしたが、ここで提供されるコードに基づいて行うのは難しくありません。
パフォーマンスアドバイザーの使用
SQL Sentry Performance Advisorはデフォルトではこの情報を追跡しませんが、データベースに情報をキャプチャし、PAに設定が変更されているかどうかを確認させ、変更されている場合は通知することができます。これを設定するには、SQLskills_ConfigDataテーブルとSQLskillsDBDataテーブルを作成し、これらのテーブルに定期的に挿入するようにスケジュールされたジョブを設定します。 SQL Sentryクライアント内で、このシリーズの以前の投稿、プロアクティブSQL Serverヘルスチェック、パート1:ディスクスペースの投稿で行ったように、カスタム条件を設定します。
カスタム条件には、2つのオプションがあります。まず、提供されたコードを実行して、履歴データをチェックし、変更があったかどうかを確認します(変更された場合は通知を送信します)。履歴データの変更を確認することは、エージェントジョブの場合と同様に、毎日実行することです。または、より積極的に、現在の実行中の値を最新のデータとより頻繁に比較することもできます。 1時間に1回、変更を探します。インスタンスの現在の設定を最新のキャプチャと照合するためのサンプルコード:
;WITH [lc] AS ( SELECT ROW_NUMBER() OVER (PARTITION BY [ConfigurationID] ORDER BY [CaptureDate] ASC) AS [RowNumber], [ConfigurationID] AS [ConfigurationID], [Name] AS [Name], [Value] AS [Value], [ValueInUse] AS [ValueInUse], [CaptureDate] AS [CaptureDate] FROM [Baselines].[ConfigData] WHERE [CaptureDate] = (SELECT MAX([CaptureDate]) FROM [Baselines].[ConfigData]) ) SELECT [lc].[Name] AS [Setting], [lc].[CaptureDate] AS [Date], [lc].[Value] AS [Last Captured Value], [lc].[ValueInUse] AS [Last Captured Value In Use], CURRENT_TIMESTAMP AS [Current Time], [c].[Value] AS [Current Value], [c].[value_in_use] AS [Current Value In Use] FROM [sys].[configurations] AS [c] LEFT OUTER JOIN [lc] ON [lc].[ConfigurationID] = [c].[configuration_id] WHERE ([lc].[Value] <> [c].[Value] OR [lc].[ValueInUse] <> [c].[value_in_use]); GO
概要
インスタンスとデータベースのオプションの確認は簡単でわかりやすく、状況によっては、この履歴情報によってトラブルシューティングの時間を大幅に節約できます。この情報をどこにも取得していない場合は、開始することをお勧めします。消防活動をしていてストレスを感じる可能性があるときに、本番環境で問題を引き起こしている原因がわからない場合に対応するよりも、問題を積極的に探す方が常に優れています。