Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Automatyczne zbieranie danych o zmianach schematu bazy danych w MS SQL Server

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

  1. 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
  2. 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ć.

  1. 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.
  2. 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


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Zapytanie cykliczne programu SQL Server

  2. Dostawca nazwanych potoków Błąd dostawcy 40 nie może otworzyć połączenia z błędem 2 programu SQL Server

  3. SQL Server 2005 Pivot na nieznanej liczbie kolumn

  4. Jak mogę wykonać kopię zapasową zdalnej bazy danych SQL Server na dysku lokalnym?

  5. serwer sql niepoprawna nazwa obiektu - ale tabele są wymienione na liście tabel SSMS