Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

So speichern Sie Verlaufsdatensätze in einer Verlaufstabelle in SQL Server

Grundsätzlich möchten Sie Änderungen an einer Tabelle nachverfolgen/prüfen, während die Größe der primären Tabelle klein bleibt.

Es gibt mehrere Möglichkeiten, dieses Problem zu lösen. Die Vor- und Nachteile jeder Methode werden unten besprochen.

1 - Audit der Tabelle mit Triggern.

Wenn Sie die Tabelle prüfen möchten (Einfügungen, Aktualisierungen, Löschungen), sehen Sie sich meine Anleitung zum Reventieren unerwünschter Transaktionen an – SQL Saturday Slide Deck w/Code – http://craftydba.com/?page_id=880. Der Trigger, der die Audit-Tabelle füllt, kann bei Bedarf Informationen aus mehreren Tabellen enthalten, da die Daten als XML gespeichert werden. Daher können Sie eine Aktion bei Bedarf rückgängig machen, indem Sie das XML analysieren. Es verfolgt, wer und was die Änderung vorgenommen hat.

Optional können Sie die Audit-Tabelle in einer eigenen Dateigruppe haben.

Description:
    Table Triggers For (Insert, Update, Delete)
    Active table has current records.
    Audit (history) table for non-active records.

Pros:
    Active table has smaller # of records.
    Index in active table is small.
    Change is quickly reported in audit table.
    Tells you what change was made (ins, del, upd)

Cons:
    Have to join two tables to do historical reporting.
    Does not track schema changes.

2 - Effiziente Datierung der Aufzeichnungen

Wenn Sie die Daten niemals aus der Audit-Tabelle löschen werden, warum markieren Sie die Zeile nicht als gelöscht, sondern behalten sie für immer? Viele Systeme wie People Soft verwenden effektives Dating, um anzuzeigen, ob ein Datensatz nicht mehr aktiv ist. In der BI-Welt wird dies als dimensionale Tabelle des Typs 2 (langsam wechselnde Dimensionen) bezeichnet. Siehe den Artikel des Data Warehouse Institute. http://www.bidw.org/datawarehousing/scd-type-2/ Jeder Datensatz hat ein Anfangs- und Enddatum.

Alle aktiven Datensätze haben ein Enddatum von null.

Description:
    Table Triggers For (Insert, Update, Delete)
    Main table has both active and historical records.

Pros:
    Historical reporting is easy.
    Change is quickly shown in main table.

Cons:
    Main table has a large # of records.
    Index of main table is large.
    Both active & history records in same filegroup.
    Does not tell you what change was made (ins, del, upd)
    Does not track schema changes.

3 - Datenerfassung ändern (Enterprise-Funktion).

Microsoft SQL Server 2008 hat das Change Data Capture-Feature eingeführt. Während dies Datenänderungen (CDC) mithilfe eines LOG-Lesegeräts nachverfolgt, fehlen Dinge wie wer und was die Änderung vorgenommen hat. MSDN-Details – http://technet.microsoft.com/en-us/library/bb522489(v=sql.105).aspx

Diese Lösung hängt von den laufenden CDC-Jobs ab. Jegliche Probleme mit dem SQL-Agenten führen zu Verzögerungen bei der Anzeige von Daten.

Siehe Datenerfassungstabellen ändern.http://technet.microsoft.com/en-us/library/bb500353(v=sql.105).aspx

Description:
    Enable change data capture

Pros:
    Do not need to add triggers or tables to capture data.
    Tells you what change was made (ins, del, upd) the _$operation field in 
    <user_defined_table_CT>
    Tracks schema changes.    

Cons:
    Only available in enterprise version.
    Since it reads the log after the fact, time delay in data showing up.
    The CDC tables do not track who or what made the change.
    Disabling CDC removes the tables (not nice)!
    Need to decode and use the _$update_mask to figure out what columns changed.

4 - Änderungsverfolgungsfunktion (alle Versionen).

Microsoft SQL Server 2008 hat die Änderungsnachverfolgungsfunktion eingeführt. Im Gegensatz zu CDC ist es in allen Versionen enthalten; Es enthält jedoch eine Reihe von TSQL-Funktionen, die Sie aufrufen müssen, um herauszufinden, was passiert ist.

Es wurde zum Zwecke der Synchronisation einer Datenquelle mit SQL Server über eine Anwendung entwickelt. Es gibt ein ganzes Synchronisations-Framework auf TechNet.

http://msdn.microsoft.com/en-us/library/bb933874.aspxhttp://msdn.microsoft.com/en-us/library/bb933994.aspxhttp://technet.microsoft.com/en-us/ library/bb934145(v=sql.105).aspx

Im Gegensatz zu CDC geben Sie an, wie lange Änderungen in der Datenbank verbleiben, bevor sie gelöscht werden. Außerdem zeichnen Einfügungen und Löschungen keine Daten auf. Updates zeichnen nur auf, welche Felder sich geändert haben.

Da Sie die SQL Server-Quelle mit einem anderen Ziel synchronisieren, funktioniert dies gut. Es ist nicht gut für die Überwachung, es sei denn, Sie schreiben einen regelmäßigen Job, um Änderungen herauszufinden.

Sie müssen diese Informationen trotzdem irgendwo speichern.

Description:
    Enable change tracking

Cons:
    Not a good auditing solution

Die ersten drei Lösungen funktionieren für Ihr Auditing. Ich mag die erste Lösung, da ich sie ausgiebig in meiner Umgebung verwende.

Mit freundlichen Grüßen

Johannes

Codeausschnitt aus Präsentation (Autos-Datenbank)

-- 
-- 7 - Auditing data changes (table for DML trigger)
-- 


-- Delete existing table
IF OBJECT_ID('[AUDIT].[LOG_TABLE_CHANGES]') IS NOT NULL 
  DROP TABLE [AUDIT].[LOG_TABLE_CHANGES]
GO


-- Add the table
CREATE TABLE [AUDIT].[LOG_TABLE_CHANGES]
(
  [CHG_ID] [numeric](18, 0) IDENTITY(1,1) NOT NULL,
  [CHG_DATE] [datetime] NOT NULL,
  [CHG_TYPE] [varchar](20) NOT NULL,
  [CHG_BY] [nvarchar](256) NOT NULL,
  [APP_NAME] [nvarchar](128) NOT NULL,
  [HOST_NAME] [nvarchar](128) NOT NULL,
  [SCHEMA_NAME] [sysname] NOT NULL,
  [OBJECT_NAME] [sysname] NOT NULL,
  [XML_RECSET] [xml] NULL,
 CONSTRAINT [PK_LTC_CHG_ID] PRIMARY KEY CLUSTERED ([CHG_ID] ASC)
) ON [PRIMARY]
GO

-- Add defaults for key information
ALTER TABLE [AUDIT].[LOG_TABLE_CHANGES] ADD CONSTRAINT [DF_LTC_CHG_DATE] DEFAULT (getdate()) FOR [CHG_DATE];
ALTER TABLE [AUDIT].[LOG_TABLE_CHANGES] ADD CONSTRAINT [DF_LTC_CHG_TYPE] DEFAULT ('') FOR [CHG_TYPE];
ALTER TABLE [AUDIT].[LOG_TABLE_CHANGES] ADD CONSTRAINT [DF_LTC_CHG_BY] DEFAULT (coalesce(suser_sname(),'?')) FOR [CHG_BY];
ALTER TABLE [AUDIT].[LOG_TABLE_CHANGES] ADD CONSTRAINT [DF_LTC_APP_NAME] DEFAULT (coalesce(app_name(),'?')) FOR [APP_NAME];
ALTER TABLE [AUDIT].[LOG_TABLE_CHANGES] ADD CONSTRAINT [DF_LTC_HOST_NAME] DEFAULT (coalesce(host_name(),'?')) FOR [HOST_NAME];
GO



--
--  8 - Make DML trigger to capture changes
--


-- Delete existing trigger
IF OBJECT_ID('[ACTIVE].[TRG_FLUID_DATA]') IS NOT NULL 
  DROP TRIGGER [ACTIVE].[TRG_FLUID_DATA]
GO

-- Add trigger to log all changes
CREATE TRIGGER [ACTIVE].[TRG_FLUID_DATA] ON [ACTIVE].[CARS_BY_COUNTRY]
  FOR INSERT, UPDATE, DELETE AS
BEGIN

  -- Detect inserts
  IF EXISTS (select * from inserted) AND NOT EXISTS (select * from deleted)
  BEGIN
    INSERT [AUDIT].[LOG_TABLE_CHANGES] ([CHG_TYPE], [SCHEMA_NAME], [OBJECT_NAME], [XML_RECSET])
    SELECT 'INSERT', '[ACTIVE]', '[CARS_BY_COUNTRY]', (SELECT * FROM inserted as Record for xml auto, elements , root('RecordSet'), type)
    RETURN;
  END

  -- Detect deletes
  IF EXISTS (select * from deleted) AND NOT EXISTS (select * from inserted)
  BEGIN
    INSERT [AUDIT].[LOG_TABLE_CHANGES] ([CHG_TYPE], [SCHEMA_NAME], [OBJECT_NAME], [XML_RECSET])
    SELECT 'DELETE', '[ACTIVE]', '[CARS_BY_COUNTRY]', (SELECT * FROM deleted as Record for xml auto, elements , root('RecordSet'), type)
    RETURN;
  END

  -- Update inserts
  IF EXISTS (select * from inserted) AND EXISTS (select * from deleted)
  BEGIN
    INSERT [AUDIT].[LOG_TABLE_CHANGES] ([CHG_TYPE], [SCHEMA_NAME], [OBJECT_NAME], [XML_RECSET])
    SELECT 'UPDATE', '[ACTIVE]', '[CARS_BY_COUNTRY]', (SELECT * FROM deleted as Record for xml auto, elements , root('RecordSet'), type)
    RETURN;
  END

END;
GO



--
--  9 - Test DML trigger by updating, deleting and inserting data
--

-- Execute an update
UPDATE [ACTIVE].[CARS_BY_COUNTRY]
SET COUNTRY_NAME = 'Czech Republic'
WHERE COUNTRY_ID = 8
GO

-- Remove all data
DELETE FROM [ACTIVE].[CARS_BY_COUNTRY];
GO

-- Execute the load
EXECUTE [ACTIVE].[USP_LOAD_CARS_BY_COUNTRY];
GO 

-- Show the audit trail
SELECT * FROM [AUDIT].[LOG_TABLE_CHANGES]
GO

-- Disable the trigger
ALTER TABLE [ACTIVE].[CARS_BY_COUNTRY] DISABLE TRIGGER [TRG_FLUID_DATA];

** Look &Feel der Audit-Tabelle **