sql >> Databáze >  >> RDS >> Sqlserver

Automatický sběr dat změn databázového schématu na MS SQL Server

Úvod

Setkali jste se někdy se situací, kdy potřebujete velmi rychle provést změny v uložené proceduře nebo pohledu? Mám, velmi často, zejména ve fázi realizace. Systém správy verzí v tomto případě bohužel nepomůže. Přesto, jak mohu pochopit, že bylo něco změněno a kdy?

Tento článek popisuje možné řešení pro automatický sběr dat o změnách databázového schématu na MS SQL Server. Jako obvykle rád uslyším jakékoli alternativní řešení.

Řešení

  1. Vytvořte dvě tabulky:první bude pro každou databázi, druhá – pro všechny databáze:
    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. Vytvořte spouštěč DDL pro databázi, která shromažďuje změny schématu:
    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

Doporučuji upravit filtr a nedělat DDL-trigger pro celý server. Je to zbytečné, protože získáte spoustu zbytečných informací. V tomto případě je lepší vytvořit spouštěč pro každou databázi.
Tento spouštěč však budete muset vypnout při složitých operacích, například při replikaci. Později jej však budete moci znovu zapnout.

  1. Budete muset shromáždit informace v jedné tabulce. Můžete to například provést pomocí úlohy v SQL Server Agent jednou týdně.
  2. Je možné shromáždit vše v jedné tabulce jiným způsobem, který preferujete.

Dále doporučuji smazat stará data.

Výsledek

V tomto článku jsem rozebral příklad implementace automatického sběru dat o změnách databázových schémat na MS SQL Server. Umožňuje nám zjistit, co a kdy bylo změněno, a v případě potřeby je vrátit zpět. Obecně může být toto řešení užitečné ve fázi implementace, kde je mnoho chyb a kdy máme různé verze kopií databází k analýze. Chcete-li zjistit důvod změn, můžete to udělat načtením historie revizí.

Přečtěte si také:

Automatický sběr dat o dokončených úkolech na MS SQL Server


  1. Hardwarové trendy databázového serveru

  2. Jak vytvořit omezení cizího klíče pomocí ON UPDATE CASCADE v SQL Server - SQL Server / Výukový program TSQL, část 79

  3. SQL Server 2008 oddělovač tisíců pro sloupec

  4. MySQL zkontroluje, zda tabulka existuje, aniž by vyvolalo výjimku