Introduktion
Har du nogensinde stået i en situation, hvor du har brug for at foretage ændringer i en lagret procedure eller en visning meget hurtigt? Det har jeg meget ofte, især på implementeringsstadiet. Desværre kan et versionskontrolsystem ikke hjælpe i dette tilfælde. Men hvordan kunne jeg forstå, at noget er blevet ændret, og hvornår?
Denne artikel beskriver en mulig løsning til automatisk dataindsamling om databaseskemaændringer i MS SQL Server. Som sædvanlig vil jeg være glad for at høre eventuelle alternative løsninger.
Løsning
- Opret to tabeller:den første vil være for hver database, den anden - for alle databaser:
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
- Opret en DDL-trigger til en database, som indsamler skemaændringer:
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
Jeg anbefaler at justere et filter og ikke lave en DDL-trigger for hele serveren. Det er ubrugeligt, da du vil få en masse unødvendig information. I dette tilfælde er det bedre at oprette en trigger for hver database.
Du bliver dog nødt til at slå denne trigger fra under komplicerede operationer, for eksempel replikering. Men senere vil du være i stand til at tænde den igen.
- Du skal samle oplysninger i en enkelt tabel. For eksempel kan du gøre det med en opgave i SQL Server Agent én gang om ugen.
- Det er muligt at samle alt i én tabel på en anden måde, du foretrækker.
Derudover anbefaler jeg at slette gamle data.
Resultat
I denne artikel har jeg analyseret et eksempel på implementering af en automatisk dataindsamling om ændringer af databaseskemaer i MS SQL Server. Det giver os mulighed for at finde ud af, hvad og hvornår der er blevet ændret, og om nødvendigt at gendanne dem. Generelt kan denne løsning være nyttig på implementeringsstadiet, hvor der er mange fejl, og når vi har forskellige versioner af databasekopier, der skal analyseres. Hvis du ønsker at finde ud af en årsag til ændringer, kan du gøre det ved at hente en revisionshistorik.
Læs også:
Automatisk dataindsamling om udførte opgaver i MS SQL Server