sql >> Database teknologi >  >> RDS >> Sqlserver

Automatisk dataindsamling af databaseskemaændringer i MS SQL Server

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

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

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


  1. Tjek om der findes en tabel i SQL Server

  2. Autoincrement i oracle til allerede oprettet tabel

  3. 7 måder at tjekke din Oracle-version på

  4. En sammenligning mellem MySQL Clone Plugin og Xtrabackup