I tuoi dati di controllo dovrebbero essere archiviati per tabella, anziché tutti in un unico posto. Quello che dovresti fare è creare una tabella di controllo per ciascuna delle tabelle che desideri monitorare e creare trigger per creare un record nella tabella di controllo per qualsiasi operazione di manipolazione dei dati sulla tabella controllata.
È decisamente consigliabile non consentire DELETE
operazioni sugli items
e item_options
tabelle - aggiungi flag come item_active
e item_option_active
in modo da poterli eliminare definitivamente. Questa è una pratica normale in situazioni in cui stai facendo cose come archiviare fatture che fanno riferimento a prodotti ordinati in passato e hai bisogno dei dati per scopi di reporting storico, ma non per l'uso quotidiano.
Le tue tabelle di controllo non sono qualcosa che dovresti usare per fare riferimento a vecchi dati, il tuo normale modello di dati dovrebbe supportare semplicemente "nascondere" i vecchi dati dove è probabile che verranno ancora utilizzati e archiviare più versioni di dati che cambieranno nel tempo.
Per l'auditing, è anche utile memorizzare il nome utente dell'ultimo utente che ha modificato un dato record:se utilizzato da un'applicazione Web, non è possibile utilizzare USER()
di MySQL funzione per ottenere tutte le informazioni utili su chi ha effettuato l'accesso. Aggiungere una colonna e popolarla significa che puoi utilizzare tali informazioni nei trigger di controllo.
NB: Presumo che non consentirai la modifica degli ID articolo in condizioni normali, il che renderebbe il tuo sistema di controllo più complesso.
Se aggiungi i flag attivi e i dati dell'ultima modifica alle tue tabelle, avranno un aspetto simile a:
Tabella degli elementi:
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 | |
+------------------+--------------+------+-----+---------+----------------+
Tabella delle opzioni degli oggetti:
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 | |
+---------------+--------------+------+-----+---------+----------------+
Le tue tabelle di controllo devono memorizzare quattro informazioni extra:
- ID audit:questo ID è univoco solo per la cronologia di questo tabella, non è un valore globale
- Modifica apportata da:l'utente del database che ha apportato la modifica
- Cambia data/ora
- Tipo di azione -
INSERT
oUPDATE
(oDELETE
se tu lo permettessi)
Le tue tabelle di controllo dovrebbero assomigliare a:
Tabella di controllo degli elementi:
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 | |
+------------------+--------------+------+-----+---------+----------------+
Tabella di controllo delle opzioni degli elementi:
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 | |
+---------------+--------------+------+-----+---------+----------------+
Non utilizzare chiavi esterne sulle tabelle di controllo; le righe nelle tabelle di controllo non sono righe figlie dei record che stanno controllando, quindi le chiavi esterne non sono di alcuna utilità.
Trigger
NB: MySQL non supporta i trigger di tipo multi-istruzione, quindi è necessario uno per ciascuno di INSERT
, UPDATE
e DELETE
(se applicabile).
I tuoi trigger devono semplicemente INSERT
tutti i NEW
valori nella tabella di controllo. Le definizioni del trigger per gli items
la tabella potrebbe essere:
/* 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;
Crea attivatori simili per item_options
tabella.
Aggiornamento:cronologia dei dati nell'e-commerce
Il controllo che abbiamo eseguito in precedenza ti consentirà di mantenere una cronologia di una determinata tabella di database, ma crea un archivio dati che non è adatto all'uso per i dati a cui è necessario accedere regolarmente.
In un sistema di e-commerce, mantenendo utilizzabile i dati storici sono importanti, in modo da poter modificare gli attributi pur presentando i vecchi valori in determinate situazioni.
Questo dovrebbe essere completamente separato dalla tua soluzione di auditing
Il modo migliore per archiviare la cronologia è creare una tabella della cronologia per ogni attributo che deve essere archiviato storicamente. Questa domanda Stackoverflow contiene alcune buone informazioni su come mantenere una cronologia di un determinato attributo .
Nella tua situazione, se sei solo preoccupato per il prezzo e il titolo, creeresti un prices
tabella e un item_titles
tavolo. Ognuno avrebbe una chiave esterna per item_options
tabella o gli items
tabella (le tabelle principali memorizzerebbero ancora il corrente prezzo o titolo) e avrebbe il prezzo o il titolo, con le relative date di validità. Queste tabelle dovrebbero avere autorizzazioni a grana fine (possibilmente basate su colonne) per evitare l'aggiornamento di effective_from
date e i valori effettivi una volta inserito il record.
Dovresti usare anche la soluzione di auditing sopra su queste tabelle.