Вашите одитни данни трябва да се съхраняват за всяка таблица, а не всички на едно място. Това, което трябва да направите, е да създадете таблица за одит за всяка от таблиците, които искате да проследявате, и да създадете тригери за създаване на запис в таблицата за одит за всяка операция по манипулиране на данни в одитираната таблица.
Определено е препоръчително да забраните DELETE
операции с items
и item_options
таблици - добавете флагове като item_active
и item_option_active
за да можете вместо това да ги изтриете меко. Това е нормална практика в ситуации, в които правите неща като съхраняване на фактури, които се позовават на продукти, поръчани в миналото, и се нуждаете от данните за целите на исторически отчети, но не и за ежедневна употреба.
Вашите одитни таблици не са нещо, което трябва да използвате за препращане към стари данни, вашият нормален модел на данни трябва да поддържа просто „скриване“ на стари данни, където е вероятно те все още да се използват, и съхраняване на множество версии на данни, които ще се променят с течение на времето.
За одит е полезно също така да съхранявате потребителското име на последния потребител, който да промени даден запис - когато се използва от уеб приложение, не можете да използвате USER()
на MySQL функция за получаване на полезна информация за това кой е влязъл. Добавянето на колона и нейното попълване означава, че можете да използвате тази информация във вашите одитни задействания.
Забележка: Предполагам, че няма да позволите идентификаторите на артикули да се променят при нормални условия – това би направило вашата система за одит по-сложна.
Ако добавите активни флагове и последно модифицирани данни към вашите таблици, те ще изглеждат нещо като:
Таблица с елементи:
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 | |
+------------------+--------------+------+-----+---------+----------------+
Таблица с опции за артикули:
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 | |
+---------------+--------------+------+-----+---------+----------------+
Вашите одитни таблици трябва да съхраняват четири допълнителни части от информация:
- ИД на одит – този идентификатор е уникален само за историята на това таблица, това не е глобална стойност
- Промяна, направена от - потребителят на базата данни, който е направил промяната
- Промяна на дата/час
- Тип действие -
INSERT
илиUPDATE
(илиDELETE
ако сте го позволили)
Вашите одитни таблици трябва да изглеждат така:
Таблица за одит на артикули:
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 | |
+------------------+--------------+------+-----+---------+----------------+
Таблица за одит на опциите за артикули:
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 | |
+---------------+--------------+------+-----+---------+----------------+
Не използвайте външни ключове във вашите одитни таблици; Редовете в одитните таблици не са дъщерни редове на записите, които одитират, така че външните ключове не са от полза.
Задействания
Забележка: MySQL не поддържа тригери от няколко типа изрази, така че имате нужда от едно за всеки от INSERT
, UPDATE
и DELETE
(ако е приложимо).
Вашите тригери просто трябва да INSERT
всички NEW
стойности в одитната таблица. Дефинициите на тригера за items
таблицата може да бъде:
/* 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;
Създайте подобни тригери за item_options
таблица.
Актуализация:История на данните в електронната търговия
Одитът, който направихме по-горе, ще ви позволи да запазите хронология на всяка дадена таблица на базата данни, но създава хранилище за данни, което не е подходящо за използване за данни, които трябва да бъдат достъпни редовно.
В система за електронна търговия, запазване използваемо историческите данни са важни, така че можете да променяте атрибути, докато все още представяте стари стойности в определени ситуации.
Това трябва да е напълно отделно от вашето решение за одит
Най-добрият начин за съхраняване на историята е да създадете хронология за всеки атрибут които трябва да се съхраняват исторически. Този въпрос на Stackoverflow има добра информация за съхраняването на история на даден атрибут .
Във вашата ситуация, ако сте загрижени само за цената и заглавието, ще създадете prices
таблица и item_titles
маса. Всеки от тях ще има външен ключ към item_options
таблица или items
таблица (главните таблици пак ще съхраняват текущите цена или заглавие) и ще има цената или заглавието с датите на влизане в сила. Тези таблици трябва да имат фино зърнени (евентуално базирани на колони) разрешения, за да се избегне актуализирането на effective_from
дати и действителните стойности, след като записът е вмъкнат.
Трябва да използвате и одитното решение по-горе за тези таблици.