Présentation
Avez-vous déjà été confronté à une situation où vous deviez apporter très rapidement des modifications à une procédure stockée ou à une vue ? J'ai, très souvent, surtout au stade de la mise en œuvre. Malheureusement, un système de contrôle de version ne peut pas aider dans ce cas. Pourtant, comment pourrais-je comprendre que quelque chose a été modifié, et quand ?
Cet article décrit une solution possible pour la collecte automatique de données sur les modifications de schéma de base de données dans MS SQL Server. Comme d'habitude, je serai heureux d'entendre toute solution alternative.
Solution
- Créez deux tables :la première sera pour chaque base de données, la seconde pour toutes les bases :
USE [DATABASE_NAME] 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 [DATABASE_NAME] 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
- Créez un déclencheur DDL pour une base de données qui collecte les modifications de schéma :
USE [DATABASE_NAME] 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%'; --there is no need in tracking changes of replication objects end end try begin catch end catch GO SET ANSI_NULLS OFF GO SET QUOTED_IDENTIFIER OFF GO ENABLE TRIGGER [SchemaLog] ON DATABASE GO
Je recommande d'ajuster un filtre et de ne pas créer de déclencheur DDL pour l'ensemble du serveur. C'est inutile, car vous obtiendrez beaucoup d'informations inutiles. Dans ce cas, il est préférable de créer un déclencheur pour chaque base de données.
Cependant, vous devrez désactiver ce déclencheur lors d'opérations compliquées, par exemple la réplication. Mais plus tard, vous pourrez le rallumer.
- Vous devrez rassembler des informations dans un seul tableau. Par exemple, vous pouvez le faire avec une tâche dans l'Agent SQL Server une fois par semaine.
- Il est possible de tout rassembler dans un tableau d'une autre manière que vous préférez.
De plus, je recommande de supprimer les anciennes données.
Résultat
Dans cet article, j'ai analysé un exemple d'implémentation d'une collecte automatique de données sur les changements de schémas de bases de données dans MS SQL Server. Cela nous permet de savoir quoi et quand a été modifié et, si nécessaire, de les annuler. En général, cette solution peut être utile au stade de la mise en œuvre où il y a beaucoup d'erreurs et lorsque nous avons différentes versions de copies de bases de données à analyser. Si vous souhaitez connaître la raison des modifications, vous pouvez le faire en récupérant un historique des révisions.
Lire aussi :
Collecte automatique de données sur les tâches terminées dans MS SQL Server