По принцип искате да проследявате/одитирате промените в таблица, като същевременно поддържате основната таблица с малък размер.
Има няколко начина за решаване на този проблем. Недостатъците и предимствата на всеки начин са обсъдени по-долу.
1 -Одит на таблицата с тригери.
Ако искате да извършите одит на таблицата (вмъкване, актуализация, изтриване), вижте как да предотвратим нежелани транзакции - SQL Saturday slide deck w/code - http://craftydba.com/?page_id=880. Тригерът, който запълва таблицата за одит, може да съдържа информация от множество таблици, ако изберете, тъй като данните се записват като XML. Следователно, можете да отмените изтриването на действие, ако е необходимо, като анализирате XML. Той проследява кой и какво е направил промяната.
По избор можете да имате таблицата за одит в собствената й файлова група.
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 - Ефективно датиране на записите
Ако никога няма да изчистите данните от таблицата за одит, защо да не маркирате реда като изтрит, но да го запазите завинаги? Много системи като хора soft използват ефективни запознанства, за да покажат дали записът вече не е активен. В света на BI това се нарича двумерна таблица от тип 2 (бавно променящи се измерения). Вижте статията на института за съхранение на данни. http://www.bidw.org/datawarehousing/scd-type-2/ Всеки запис има начална и крайна дата.
Всички активни записи имат крайна дата нула.
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 – Промяна на улавянето на данни (функция за предприятие).
Micorsoft SQL Server 2008 въведе функцията за улавяне на данни за промяна. Докато това проследява промяната на данните (CDC) с помощта на четец на LOG след факта, липсват неща като кой и какво е направил промяната. Подробности за MSDN - http://technet.microsoft.com/en-us/library/bb522489(v=sql.105).aspx
Това решение зависи от изпълняваните задачи на CDC. Всички проблеми с sql агента ще причинят забавяне на показването на данните.
Вижте таблиците за улавяне на промените.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 – Промяна на функцията за проследяване (всички версии).
Micorsoft SQL Server 2008 въведе функцията за проследяване на промените. За разлика от CDC, той идва с всички версии; Той обаче идва с куп TSQL функции, които трябва да извикате, за да разберете какво се е случило.
Той е проектиран с цел синхронизиране на един източник на данни със SQL сървър чрез приложение. В TechNet има цяла рамка за синхронизиране.
http://msdn.microsoft.com/en-us/library/bb933874.aspxhttp://msdn.microsoft.com/en-us/library/bb933994.aspxhttp://technet.microsoft.com/en-us/ библиотека/bb934145(v=sql.105).aspx
За разлика от CDC, вие посочвате колко дълго траят промените в базата данни, преди да бъдат изчистени. Освен това вмъкванията и изтриванията не записват данни. Актуализациите записват само промененото поле.
Тъй като синхронизирате източника на SQL сървър с друга цел, това работи добре. Не е добре за одит, освен ако не напишете периодично задание, за да разберете промените.
Все пак ще трябва да съхранявате тази информация някъде.
Description:
Enable change tracking
Cons:
Not a good auditing solution
Първите три решения ще работят за вашия одит. Харесвам първото решение, тъй като го използвам широко в моята среда.
С уважение
Джон
Кодов фрагмент от презентацията (база данни за автомобили)
--
-- 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];
** Изглед и усещане на таблицата за одит **