MS SQL Serverのデータベーススキーマ変更に関するデータの自動収集

まえがき



ストアドプロシージャやビュー、またはその他の場所を非常に迅速に変更する必要があるという事実に遭遇したことはありますか? これは私でよく起こります。 そして、実装期間中、一般的に、常に。 そして、ここで私はバージョン管理システムがいつも助けられるとは限らないのではないかと心配しています。 しかし、何が変わったのかをどのように理解していますか? どのように変化しましたか? 変更前に何が起こったのですか? いつ変更されましたか?







この記事はガイドではありません。 その中で、私はこの問題の可能な解決策を示したかっただけです。 代替ソリューションが提供されれば嬉しいです。









解決策



1)2つのテーブルを作成します(最初のテーブルは監視対象データベースごとに、2番目はサーバーのすべての監視対象データベース用):







コード
USE [__] GO SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE TABLE [srv].[ddl_log]( [DDL_Log_GUID] [uniqueidentifier] NOT NULL, [PostTime] [datetime] NOT NULL, [DB_Login] [nvarchar](255) NULL, [DB_User] [nvarchar](255) NULL, [Event] [nvarchar](255) NULL, [TSQL] [nvarchar](max) NULL, CONSTRAINT [PK_ddl_log] PRIMARY KEY CLUSTERED ( [DDL_Log_GUID] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] GO ALTER TABLE [srv].[ddl_log] ADD CONSTRAINT [DF_ddl_log_DDL_Log_GUID] DEFAULT (newid()) FOR [DDL_Log_GUID] GO USE [__] GO SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE TABLE [srv].[ddl_log_all]( [DDL_Log_GUID] [uniqueidentifier] NOT NULL, [Server_Name] [nvarchar](255) NOT NULL, [DB_Name] [nvarchar](255) NOT NULL, [PostTime] [datetime] NOT NULL, [DB_Login] [nvarchar](255) NULL, [DB_User] [nvarchar](255) NULL, [Event] [nvarchar](255) NULL, [TSQL] [nvarchar](max) NULL, [InsertUTCDate] [datetime] NOT NULL, CONSTRAINT [PK_ddl_log_all] PRIMARY KEY CLUSTERED ( [DDL_Log_GUID] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] GO ALTER TABLE [srv].[ddl_log_all] ADD CONSTRAINT [DF_ddl_log_all_DDL_Log_GUID] DEFAULT (newid()) FOR [DDL_Log_GUID] GO ALTER TABLE [srv].[ddl_log_all] ADD CONSTRAINT [DF_ddl_log_all_InsertUTCDate] DEFAULT (getutcdate()) FOR [InsertUTCDate] GO
      
      





2)スキーマの変更を収集するデータベースでDDLトリガーを作成します。







コード
 USE [__] GO SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE TRIGGER [SchemaLog] ON DATABASE --ALL SERVER FOR DDL_DATABASE_LEVEL_EVENTS AS SET NOCOUNT ON; SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; DECLARE @data XML begin try if(CURRENT_USER<>'NT AUTHORITY\NETWORK SERVICE' and SYSTEM_USER<>'NT AUTHORITY\NETWORK SERVICE') begin SET @data = EVENTDATA(); INSERT srv.ddl_log( PostTime, DB_Login, DB_User, Event, TSQL ) select GETUTCDATE(), CONVERT(nvarchar(255), SYSTEM_USER), CONVERT(nvarchar(255), CURRENT_USER), @data.value('(/EVENT_INSTANCE/EventType)[1]', 'nvarchar(255)'), @data.value('(/EVENT_INSTANCE/TSQLCommand)[1]', 'nvarchar(max)') where @data.value('(/EVENT_INSTANCE/EventType)[1]', 'nvarchar(255)') not in('UPDATE_STATISTICS', 'ALTER_INDEX') and @data.value('(/EVENT_INSTANCE/TSQLCommand)[1]', 'nvarchar(max)') not like '%Msmerge%'; --       end end try begin catch end catch GO SET ANSI_NULLS OFF GO SET QUOTED_IDENTIFIER OFF GO ENABLE TRIGGER [SchemaLog] ON DATABASE GO
      
      





もちろん、フィルターを設定する必要があります。たとえば、インデックスの変更を追跡したり統計を更新したりしたくないためです(ただし、主観的なものであり、場合によっては必要になりますが、他のものは必要ありません)。 また、サーバー全体でDDLトリガーを実行することはお勧めしません。 私は試してみましたが、信じられますが、私はこれほど多くの追加情報をどこにも見たことがなく、そのような成長率でさえ見ました。 そうではありませんが、データが船のAIS受信機から来るのを見ました。 しかし、一般的に、私はそれをお勧めしません。 監視対象データベースごとにトリガーを作成することをお勧めします。

たとえば、レプリケーションの複雑な初期化操作中は、このトリガーを無効にする必要があります。 しかし、その後、再びオンにすることができます。







3)次に、何らかの方法で、単一のテーブルに情報を収集します(たとえば、エージェントを1日に1回設定することにより)







4)複数のサーバーの場合、何らかの方法でも1つのテーブルにすべてを収集できます。







非常に古いデータ(たとえば、1か月以上前のもの)を削除することを忘れないでください。







結果



この記事では、MS SQL Serverのデータベーススキーマ変更に関する自動データ収集の実装例を検討しました。これにより、何がいつ、何が変更されたかを見つけるだけでなく、これらの変更をすばやくロールバックできます。 基本的に、このメカニズムは、実装段階、ほとんどの間違いが発生した場合、および実装者(私を含む)によって作成されたデータベースのコピーが非常に分岐するため、何が、いつ、なぜ変更されたかを分析する必要があります。 変更の理由は、特定の実装者(および自分)から、変更履歴を受け取っただけで見つけることができます。これは、残念ながら、大まかな活動中にすべてが頭に記憶されているわけではないためです。








All Articles