Wprowadzenie
Czy kiedykolwiek spotkałeś się z sytuacją, w której musisz bardzo szybko wprowadzić zmiany w procedurze składowanej lub widoku? Bardzo często, zwłaszcza na etapie realizacji. Niestety system kontroli wersji nie może w tym przypadku pomóc. Mimo to, jak mogę zrozumieć, że coś zostało zmodyfikowane i kiedy?
W tym artykule opisano możliwe rozwiązanie automatycznego zbierania danych o zmianach schematu bazy danych w MS SQL Server. Jak zwykle z przyjemnością wysłucham wszelkich alternatywnych rozwiązań.
Rozwiązanie
- Utwórz dwie tabele:pierwsza będzie dla każdej bazy danych, druga dla wszystkich baz danych:
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
- Utwórz wyzwalacz DDL dla bazy danych, która zbiera zmiany w schemacie:
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
Zalecam dostosowanie filtra i nie tworzenie wyzwalacza DDL dla całego serwera. Jest to bezużyteczne, ponieważ otrzymasz wiele niepotrzebnych informacji. W takim przypadku lepiej jest utworzyć wyzwalacz dla każdej bazy danych.
Jednakże podczas skomplikowanych operacji, na przykład replikacji, konieczne będzie wyłączenie tego wyzwalacza. Ale później będziesz mógł go ponownie włączyć.
- Będziesz musiał zebrać informacje w jednej tabeli. Na przykład możesz to zrobić za pomocą zadania w agencie SQL Server raz w tygodniu.
- Możliwe jest zebranie wszystkiego na jednym stole w inny, preferowany sposób.
Dodatkowo polecam usunięcie starych danych.
Wynik
W artykule przeanalizowałem przykład wdrożenia automatycznego zbierania danych o zmianach schematów baz danych w MS SQL Server. Pozwala nam dowiedzieć się, co i kiedy zostało zmodyfikowane i w razie potrzeby je cofnąć. Generalnie rozwiązanie to może być pomocne na etapie wdrożenia, gdzie pojawia się dużo błędów i gdy mamy do analizy różne wersje kopii baz danych. Jeśli chcesz znaleźć przyczynę zmian, możesz to zrobić, pobierając historię zmian.
Przeczytaj także:
Automatyczne zbieranie danych o zakończonych zadaniach w MS SQL Server