Twoje dane kontrolne powinny być przechowywane według tabeli, a nie wszystkie w jednym miejscu. Wystarczy utworzyć tabelę audytu dla każdej tabeli, którą chcesz śledzić, i utworzyć wyzwalacze, aby utworzyć rekord w tabeli audytu dla dowolnej operacji manipulacji danymi w tabeli audytowanej.
Zdecydowanie zaleca się wyłączenie DELETE
operacje na items
i item_options
tabele - dodaj flagi, takie jak item_active
i item_option_active
dzięki czemu możesz je softdelete zamiast. Jest to normalna praktyka w sytuacjach, gdy robisz takie rzeczy, jak przechowywanie faktur, które odnoszą się do produktów zamówionych w przeszłości i potrzebujesz danych do celów raportowania historycznego, ale nie do codziennego użytku.
Twoje tabele kontrolne nie są czymś, czego powinieneś używać do odwoływania się do starych danych, Twój normalny model danych powinien obsługiwać po prostu „ukrywanie” starych danych tam, gdzie prawdopodobnie nadal będą używane, oraz przechowywanie wielu wersji danych, które będą się zmieniać w czasie.
W przypadku audytu przydatne jest również przechowywanie nazwy użytkownika ostatniego użytkownika, który modyfikował dany rekord — w przypadku użycia z aplikacji internetowej nie można użyć funkcji USER()
MySQL funkcja, aby uzyskać przydatne informacje o tym, kto jest zalogowany. Dodanie kolumny i wypełnienie jej oznacza, że możesz wykorzystać te informacje w wyzwalaczach audytu.
Uwaga: Zakładam, że w normalnych warunkach nie zezwolisz na zmianę identyfikatorów produktów — to uczyniłoby Twój system kontroli bardziej złożonym.
Jeśli dodasz do tabel aktywne flagi i dane ostatnio zmodyfikowane przez, będą one wyglądać mniej więcej tak:
Tabela przedmiotów:
mysql> desc items;
+------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------------+--------------+------+-----+---------+----------------+
| item_id | int(11) | NO | PRI | NULL | auto_increment |
| item_name | varchar(100) | YES | | NULL | |
| item_description | text | YES | | NULL | |
| item_active | tinyint(4) | YES | | NULL | |
| modified_by | varchar(50) | YES | | NULL | |
+------------------+--------------+------+-----+---------+----------------+
Tabela opcji pozycji:
mysql> desc item_options;
+---------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+--------------+------+-----+---------+----------------+
| option_id | int(11) | NO | PRI | NULL | auto_increment |
| item_id | int(11) | YES | MUL | NULL | |
| option_name | varchar(100) | YES | | NULL | |
| option_price | int(11) | YES | | NULL | |
| option_active | tinyint(4) | YES | | NULL | |
| modified_by | varchar(50) | YES | | NULL | |
+---------------+--------------+------+-----+---------+----------------+
Twoje tabele kontrolne muszą przechowywać cztery dodatkowe informacje:
- Identyfikator audytu — ten identyfikator jest unikalny tylko dla historii tego tabela, to nie jest wartość globalna
- Zmiana dokonana przez — użytkownik bazy danych, który dokonał zmiany
- Zmień datę/godzinę
- Typ akcji —
INSERT
lubUPDATE
(lubDELETE
jeśli na to pozwalasz)
Twoje tabele kontrolne powinny wyglądać mniej więcej tak:
Tabela kontroli pozycji:
mysql> desc items_audit;
+------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------------+--------------+------+-----+---------+----------------+
| audit_id | int(11) | NO | PRI | NULL | auto_increment |
| item_id | int(11) | YES | | NULL | |
| item_name | varchar(100) | YES | | NULL | |
| item_description | text | YES | | NULL | |
| item_active | tinyint(4) | YES | | NULL | |
| modified_by | varchar(50) | YES | | NULL | |
| change_by | varchar(50) | YES | | NULL | |
| change_date | datetime | YES | | NULL | |
| action | varchar(10) | YES | | NULL | |
+------------------+--------------+------+-----+---------+----------------+
Tabela kontroli opcji pozycji:
mysql> desc item_options_audit;
+---------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+--------------+------+-----+---------+----------------+
| audit_id | int(11) | NO | PRI | NULL | auto_increment |
| option_id | int(11) | YES | | NULL | |
| item_id | int(11) | YES | | NULL | |
| option_name | varchar(100) | YES | | NULL | |
| option_price | int(11) | YES | | NULL | |
| option_active | tinyint(4) | YES | | NULL | |
| modified_by | varchar(50) | YES | | NULL | |
| change_by | varchar(50) | YES | | NULL | |
| change_date | datetime | YES | | NULL | |
| action | varchar(10) | YES | | NULL | |
+---------------+--------------+------+-----+---------+----------------+
Nie używaj kluczy obcych w tabelach kontrolnych; wiersze w tabelach kontroli nie są wierszami podrzędnymi rekordów, które są kontrolowane, więc klucze obce są bezużyteczne.
Wyzwalacze
Uwaga: MySQL nie obsługuje wyzwalaczy typu multi-statement, więc potrzebujesz jednego dla każdego z INSERT
, UPDATE
i DELETE
(jeśli dotyczy).
Twoje wyzwalacze muszą po prostu INSERT
wszystkie NEW
wartości do tabeli audytu. Definicje wyzwalaczy dla items
tabela może być:
/* Trigger for INSERT statements on the items table */
CREATE DEFINER=`root`@`localhost` TRIGGER trigger_items_insert_audit
AFTER INSERT ON items
FOR EACH ROW BEGIN
INSERT INTO items_audit (
item_id, item_name, item_description,
item_active, modified_by, change_by,
change_date, action
) VALUES (
NEW.item_id, NEW.item_name, NEW.item_description,
NEW.item_active, NEW.modified_by, USER(),
NOW(), 'INSERT'
);
END;
/* Trigger for UPDATE statements on the items table */
CREATE DEFINER=`root`@`localhost` TRIGGER trigger_items_update_audit
AFTER UPDATE ON items
FOR EACH ROW BEGIN
INSERT INTO items_audit (
item_id, item_name, item_description,
item_active, modified_by, change_by,
change_date, action
) VALUES (
NEW.item_id, NEW.item_name, NEW.item_description,
NEW.item_active, NEW.modified_by, USER(),
NOW(), 'UPDATE'
);
END;
Utwórz podobne wyzwalacze dla item_options
tabela.
Aktualizacja:historia danych w handlu elektronicznym
Audyt, który przeprowadziliśmy powyżej, pozwoli Ci zachować historię dowolnej tabeli bazy danych, ale stworzy magazyn danych, który nie jest odpowiedni do użycia w przypadku danych, do których należy regularnie uzyskiwać dostęp.
W systemie e-commerce utrzymanie użyteczności dane historyczne są ważne, aby można było zmieniać atrybuty, jednocześnie prezentując stare wartości w określonych sytuacjach.
Powinno to być całkowicie oddzielone od rozwiązania do audytu
Najlepszym sposobem przechowywania historii jest utworzenie tabeli historii dla każdego atrybutu który musi być przechowywany historycznie. To pytanie Stackoverflow zawiera dobre informacje na temat przechowywania historii danego atrybutu .
W Twojej sytuacji, jeśli interesuje Cię tylko cena i tytuł, utworzysz prices
tabelę i item_titles
stół. Każdy z nich miałby klucz obcy do item_options
tabela lub items
tabela (tabele główne nadal przechowują bieżące cena lub tytuł) i będzie zawierała cenę lub tytuł wraz z datami ich wejścia w życie. Te tabele powinny mieć szczegółowe (prawdopodobnie oparte na kolumnach) uprawnienia, aby uniknąć aktualizacji effective_from
daty i rzeczywiste wartości po wstawieniu rekordu.
Powinieneś użyć powyższego rozwiązania audytu również w tych tabelach.