2010-01-06 9 views
118

Za każdym razem, gdy potrzebuję zaprojektować nową bazę danych, spędzam sporo czasu, zastanawiając się, w jaki sposób powinienem skonfigurować schemat bazy danych, aby zachować dziennik inspekcji z zmian.Projektowanie bazy danych do rejestrowania kontroli

Niektóre pytania były już zadawane tutaj na ten temat, ale nie zgadzam się, że istnieje pojedynczy najlepszym rozwiązaniem dla wszystkich scenariuszy:

Natknąłem się również na to interesting article on Maintaining a Log of Database Changes, które próbuje wymienić pro i przeciw eac h podejście. Jest bardzo dobrze napisany i ma interesujące informacje, ale jeszcze bardziej utrudniał mi podejmowanie decyzji.

Moje pytanie brzmi: Czy istnieje odniesienie, że mogę używać, może książka lub coś podobnego drzewa decyzyjnego, że mogę odnosić się zdecydować, w którą stronę mam iść na podstawie niektórych zmiennych wejściowych, takich jak:

  • dojrzałość schematu bazy danych
  • Jak dzienniki będzie odpytywany
  • prawdopodobieństwo, że będzie trzeba odtworzyć rekordy
  • Co ważniejsze: zapis lub odczyt RLM rformance
  • charakter wartości, które są rejestrowane (String, liczby, Blobs) przestrzeni
  • Storage dostępnych

metod, które znam są:

1. Dodawanie kolumn do tworzone i zmodyfikowane data i użytkownik przykład

Tabela:

  • id
  • wartość_1
  • wartość_2
  • VALUE_3
  • CREATED_DATE
  • modifed_date
  • created_by
  • modified_by

Główne zalety: Tracimy historię zmian. Nie można wycofać po zatwierdzeniu.

2.Wstawić tylko tabele

Table example:

  • ID
  • value_1
  • wartość_2
  • VALUE_3
  • z
  • do
  • usunięty (typ logiczny)
  • użytkownik

Główne zalety: Jak zachować klucze obce na bieżąco? Ogromna przestrzeń potrzebna

3. Tworzenie osobnej tabeli Historia dla każdej tabeli

przykład stół Historia:

  • id
  • wartość_1
  • wartość_2
  • VALUE_3
  • value_4
  • użytkownik
  • usunięte (logiczna)
  • datownik

Główne wady: wymaga powielić wszystkie tabele zbadane. Jeśli schemat się zmieni, będzie potrzebne migrację wszystkich dzienników.

4. Tworzenie skonsolidowanej Historia tabela dla wszystkich tabel

przykład stół Historia:

  • table_name
  • pole
  • użytkownik
  • new_value
  • usunięte (logiczna)
  • Znacznik czasu

Główne zalety: Czy będę w stanie odtworzyć zapisy (wycofywanie), jeśli będą potrzebne w łatwy sposób? Kolumna new_value musi mieć duży ciąg znaków, aby mogła obsługiwać wszystkie typy kolumn.

+0

pokrewne: http://stackoverflow.com/questions/9852703/store-all-data-changes-with-every-details-stackoverflow-like – Kaii

+0

i co na temat korzystania z bazy historii zamiast tabel? – Jowen

+0

Może możesz sprawdzić projekt https://github.com/airblade/paper_trail – zx1986

Odpowiedz

72

Jedną z metod używanych przez kilka platform wiki jest oddzielenie danych identyfikujących i kontrolowanej treści. Zwiększa złożoność, ale kończy się ścieżką audytu kompletnych rekordów, a nie tylko listą edytowanych pól, które następnie trzeba zsumować, aby dać użytkownikowi wyobrażenie o tym, jak wyglądała stara płyta.

Tak na przykład, jeśli miał tabeli o nazwie szans śledzić oferty sprzedaży, to rzeczywiście stworzyć dwie oddzielne tabele:

Szanse
Opportunities_Content (czy coś takiego)

Tabela zawierająca informacje, których można użyć do jednoznacznej identyfikacji rekordu, zawierała klucz podstawowy, do którego chcesz się odwołać. oreign kluczowe relacje. Tabela Możliwości zawiera wszystkie pola, które użytkownicy mogą zmienić i dla których chcielibyśmy zachować dziennik kontroli. Każdy rekord w tabeli zawierałby własne dane PK oraz dane zmodyfikowane przez i zmodyfikowane daty. Tabela zawiera odniesienie do aktualnej wersji, a także informacje o tym, kiedy główny rekord został pierwotnie utworzony i przez kogo.

Oto prosty przykład:

CREATE TABLE dbo.Page( 
    ID int PRIMARY KEY, 
    Name nvarchar(200) NOT NULL, 
    CreatedByName nvarchar(100) NOT NULL, 
    CurrentRevision int NOT NULL, 
    CreatedDateTime datetime NOT NULL 

i zawartość:

CREATE TABLE dbo.PageContent(
    PageID int NOT NULL, 
    Revision int NOT NULL, 
    Title nvarchar(200) NOT NULL, 
    User nvarchar(100) NOT NULL, 
    LastModified datetime NOT NULL, 
    Comment nvarchar(300) NULL, 
    Content nvarchar(max) NOT NULL, 
    Description nvarchar(200) NULL 

to pewnie zrobić PK tabeli zawartości wieloliterowy klucz kolumna z IdStrony i przeglądu przewidzianego Weryfikacja była rodzaj tożsamości. Możesz użyć kolumny wersji jako FK. Następnie ciągnij skonsolidowany rekord przez JOINING w ten sposób:

SELECT * FROM Page 
JOIN PageContent ON CurrentRevision = Revision AND ID = PageID 

Może być tam trochę błędów ... to jest poza zasięgiem mojej głowy. Powinien jednak dać ci wyobrażenie o alternatywnym wzorze.

Josh

+5

Jakieś powody przyjęcia sprawy? –

+8

Pod względem dobrego podejścia do audytu, ale w przypadku produkcji, przygotowanie oddzielnej tabeli kontroli dla każdej tabeli w bazie danych zajmie dużo czasu, zapisanie wyzwalaczy dla każdej tabeli w celu przechwycenia zmian i zapisania ich w tabeli kontroli. Ponadto ogromne wyzwanie przy opracowywaniu raportu z pojedynczego audytu dla wszystkich tabel, ponieważ każda tabela kontroli ma inną strukturę. –

+9

Jeśli pisanie i utrzymywanie skryptów dla każdej tabeli stanowi problem dla organizacji, która zamierza zarządzać poddawaną audytowi bazą danych, naturalnie zaleciłbym zatrudnienie doświadczonego administratora DBA lub wysoce elastycznego i bardzo doświadczonego inżyniera oprogramowania z odpowiednim doświadczeniem w tworzeniu audytów. bazy danych. – Hardryv

6

Nie znam żadnego odniesienia, ale jestem pewien, że ktoś coś napisał.

Jednakże, jeśli celem jest po prostu mieć zapis tego, co się stało-najbardziej typowym użytkowaniem audytu log-to dlaczego nie po prostu zachować wszystko:

timestamp 
username 
ip_address 
procedureName (if called from a stored procedure) 
database 
table 
field 
accesstype (insert, delete, modify) 
oldvalue 
newvalue 

Przypuszczalnie ten jest utrzymywany przez wyzwalacz.

+0

Możesz nawet zrobić prostsze: (znacznik czasu, użytkownik, polecenie sql). –

+0

Nie znam żadnego sposobu na uzyskanie tego w serwerze bazy danych, ale oczywiście można to zrobić z zewnątrz dość łatwo. – wallyk

+2

Wydaje mi się, że jest to ten sam wzorzec projektowy co czwarta opcja pokazana w oryginalnym pytaniu. – givanse

10

Jeśli używasz programu SQL Server 2008, prawdopodobnie powinieneś rozważyć zmianę przechwytywania danych. To jest nowe na 2008 rok i może zaoszczędzić Ci znaczną część pracy.

+0

Więcej informacji tutaj: http://msdn.microsoft.com/en-us/library/cc645858.aspx – RedFilter

+0

tutaj jest link do informacji śledzenia zmian SQL 2012. http://msdn.microsoft.com/en-us/library/bb933994.aspx +1 za korzystanie z wbudowanej funkcjonalności, nie ma potrzeby ponownego wynajdywania koła. – Chris

+2

@ Chris, czy kiedykolwiek używałeś go sam? Rzeczywiście, śledzi wszystko ... ale możliwość uzyskania z niego użytecznej informacji to zupełnie inna historia. Nie mogę użyć koła ciągnika do mojego roweru. – Jowen

3

Myślę, że nie ma to jak drzewo decyzyjne. Ponieważ niektóre wady i zalety (lub wymagania) nie są tak naprawdę policzalne. Jak na przykład mierzysz dojrzałość?

Po prostu dostosuj swoje wymagania biznesowe do rejestrowania kontroli. Spróbuj przewidzieć, jak te wymagania mogą się zmienić w przyszłości i wygeneruj wymagania techniczne. Teraz możesz porównać go z zaletami i wadami i wybrać właściwą/najlepszą opcję.

Bądź pewny, nieważne, jak zdecydujesz, zawsze znajdzie się ktoś, kto myśli, że podjąłeś błędną decyzję. Jednak odrobiłeś pracę domową i uzasadniasz swoją decyzję.

1

Stworzymy małą przykładową bazę danych dla aplikacji blogującej.Wymagane są dwie tabele:

blog: przechowuje unikalny identyfikator posta, tytuł, treść i usuniętą flagę. audit: przechowuje podstawowy zestaw zmian historycznych z identyfikatorem rekordu, identyfikatorem wpisu bloga, typem zmiany (NOWA, EDYCJA lub USUŃ) oraz datą/godziną tej zmiany. Poniższe SQL tworzy indeksy blog i usuniętej kolumny:

CREATE TABLE `blog` (
    `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, 
    `title` text, 
    `content` text, 
    `deleted` tinyint(1) unsigned NOT NULL DEFAULT '0', 
    PRIMARY KEY (`id`), 
    KEY `ix_deleted` (`deleted`) 
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='Blog posts'; 

Poniższe SQL tworzy tablicę audit. Wszystkie kolumny są indeksowane, a klucz obcy jest zdefiniowany dla parametru audit.blog_id, który odwołuje się do blog.id. Dlatego, gdy fizycznie usuniemy wpis blogu, jego pełna historia audytu również zostanie usunięta.

CREATE TABLE `audit` (
    `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, 
    `blog_id` mediumint(8) unsigned NOT NULL, 
    `changetype` enum('NEW','EDIT','DELETE') NOT NULL, 
    `changetime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 
    PRIMARY KEY (`id`), 
    KEY `ix_blog_id` (`blog_id`), 
    KEY `ix_changetype` (`changetype`), 
    KEY `ix_changetime` (`changetime`), 
    CONSTRAINT `FK_audit_blog_id` FOREIGN KEY (`blog_id`) REFERENCES `blog` (`id`) ON DELETE CASCADE ON UPDATE CASCADE 
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; 
Powiązane problemy