Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Como armazenar registros históricos em uma tabela de histórico no SQL Server


Basicamente, você está procurando rastrear/auditar alterações em uma tabela enquanto mantém a tabela primária pequena em tamanho.

Existem várias maneiras de resolver esse problema. Os contras e prós de cada maneira são discutidos abaixo.

1 - Auditoria da tabela com acionadores.

Se você deseja auditar a tabela (inserções, atualizações, exclusões), veja meu como reventar transações indesejadas - deck de slides do SQL Saturday com código - http://craftydba.com/?page_id=880. O gatilho que preenche a tabela de auditoria pode conter informações de várias tabelas, se você escolher, pois os dados são salvos como XML. Portanto, você pode cancelar a exclusão de uma ação, se necessário, analisando o XML. Ele rastreia quem e o que fez a mudança.

Opcionalmente, você pode ter a tabela de auditoria em seu próprio grupo de arquivos.
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 - Data efetiva dos registros

Se você nunca vai limpar os dados da tabela de auditoria, por que não marcar a linha como excluída, mas mantê-la para sempre? Muitos sistemas, como as pessoas, usam a datação efetiva para mostrar se um registro não está mais ativo. No mundo de BI, isso é chamado de tabela dimensional tipo 2 (dimensões que mudam lentamente). Consulte o artigo do instituto de data warehouse. http://www.bidw.org/datawarehousing/scd-type-2/ Cada registro tem uma data de início e término.

Todos os registros ativos têm uma data de término nula.
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 - Alterar captura de dados (recurso corporativo).

O Microsoft SQL Server 2008 introduziu o recurso de captura de dados alterados. Embora isso rastreie a alteração de dados (CDC) usando um leitor de LOG após o fato, faltam coisas como quem e o que fez a alteração. Detalhes do MSDN - http://technet.microsoft.com/en-us/library/bb522489(v=sql.105).aspx

Essa solução depende dos trabalhos do CDC em execução. Quaisquer problemas com o agente sql causarão atrasos na exibição dos dados.

Consulte as tabelas de captura de dados de alteração.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 - Recurso de acompanhamento de alterações (todas as versões).

O Microsoft SQL Server 2008 introduziu o recurso de controle de alterações. Ao contrário do CDC, ele vem com todas as versões; No entanto, ele vem com várias funções TSQL que você precisa chamar para descobrir o que aconteceu.

Ele foi projetado para sincronizar uma fonte de dados com o SQL Server por meio de um aplicativo. Há todo um trabalho de estrutura de sincronização no 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

Ao contrário do CDC, você especifica quanto tempo duram as alterações no banco de dados antes de serem limpas. Além disso, inserções e exclusões não registram dados. As atualizações registram apenas o campo alterado.

Como você está sincronizando a origem do SQL Server com outro destino, isso funciona bem. Não é bom para auditoria, a menos que você escreva um trabalho periódico para descobrir as alterações.

Você ainda terá que armazenar essa informação em algum lugar.
Description:
    Enable change tracking

Cons:
    Not a good auditing solution

As três primeiras soluções funcionarão para sua auditoria. Eu gosto da primeira solução, pois a uso extensivamente em meu ambiente.

Sinceramente

John

Snippet de código da apresentação (banco de dados de automóveis)
-- 
-- 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 da tabela de auditoria **