Uw auditgegevens moeten per tabel worden opgeslagen, in plaats van allemaal op één plaats. Wat u zou doen, is een controletabel maken voor elk van de tabellen die u wilt volgen, en triggers maken om een record in de controletabel te maken voor elke gegevensmanipulatiebewerking op de gecontroleerde tabel.
Het is zeker aan te raden om DELETE
niet toe te staan bewerkingen op de items
en item_options
tabellen - voeg vlaggen toe zoals item_active
en item_option_active
zodat u ze in plaats daarvan zacht kunt verwijderen. Dit is normaal in situaties waarin u bijvoorbeeld facturen opslaat die verwijzen naar producten die in het verleden zijn besteld, en de gegevens nodig hebt voor historische rapportagedoeleinden, maar niet voor dagelijks gebruik.
Uw controletabellen zijn niet iets dat u zou moeten gebruiken om naar oude gegevens te verwijzen, uw normale gegevensmodel zou het eenvoudig moeten ondersteunen om oude gegevens te "verbergen" waar het waarschijnlijk is dat ze nog zullen worden gebruikt, en om meerdere versies van gegevens op te slaan die in de loop van de tijd zullen veranderen.
Voor controle is het ook handig om de gebruikersnaam van de laatste gebruiker op te slaan om een bepaald record te wijzigen - wanneer gebruikt vanuit een webtoepassing, kunt u MySQL's USER()
niet gebruiken functie om alle nuttige informatie te krijgen over wie is ingelogd. Door een kolom toe te voegen en te vullen, kunt u die informatie gebruiken in uw controletriggers.
NB: Ik ga ervan uit dat u onder normale omstandigheden niet toestaat dat item-ID's worden gewijzigd - dat zou uw controlesysteem complexer maken.
Als u actieve vlaggen en laatst gewijzigde gegevens aan uw tabellen toevoegt, zien ze er ongeveer zo uit:
Itemtabel:
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 | |
+------------------+--------------+------+-----+---------+----------------+
Tabel met itemopties:
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 | |
+---------------+--------------+------+-----+---------+----------------+
Uw controletabellen moeten vier extra stukjes informatie bevatten:
- Audit-ID - deze ID is alleen uniek voor de geschiedenis van dit tabel, het is geen globale waarde
- Wijziging aangebracht door - de databasegebruiker die de wijziging heeft aangebracht
- Wijzig datum/tijd
- Actietype -
INSERT
ofUPDATE
(ofDELETE
als je het toestond)
Uw controletabellen zouden er ongeveer zo uit moeten zien:
Itemcontroletabel:
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 | |
+------------------+--------------+------+-----+---------+----------------+
Auditietabel itemopties:
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 | |
+---------------+--------------+------+-----+---------+----------------+
Gebruik geen externe sleutels op uw controletabellen; de rijen in de controletabellen zijn geen onderliggende rijen van de records die ze controleren, dus externe sleutels hebben geen enkel nut.
Triggers
NB: MySQL ondersteunt geen multi-statement-type triggers, dus u hebt er een nodig voor elk van INSERT
, UPDATE
en DELETE
(indien van toepassing).
Je triggers moeten gewoon INSERT
alle NEW
waarden in de controletabel. De triggerdefinities voor de items
tabel kan zijn:
/* 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;
Maak vergelijkbare triggers voor de item_options
tafel.
Update:gegevensgeschiedenis in e-commerce
Met de controle die we hierboven hebben uitgevoerd, kunt u een geschiedenis bijhouden van een bepaalde databasetabel, maar wordt een gegevensopslag gemaakt die niet geschikt is voor gegevens die regelmatig moeten worden geopend.
In een e-commerce systeem, bruikbaar . houden historische gegevens zijn belangrijk, zodat u kenmerken kunt wijzigen terwijl u in bepaalde situaties nog steeds oude waarden presenteert.
Dit moet volledig los staan van uw controleoplossing
De beste manier om geschiedenis op te slaan is door een geschiedenistabel te maken voor elk attribuut dat moet historisch worden opgeslagen. Deze Stackoverflow-vraag bevat goede informatie over het bijhouden van een geschiedenis van een bepaald attribuut .
Als u zich in uw situatie alleen zorgen maakt over prijs en titel, maakt u een prices
tabel, en een item_titles
tafel. Elk zou een externe sleutel hebben voor de item_options
tabel of de items
tabel (de hoofdtabellen bewaren nog steeds de huidige prijs of titel), en zou de prijs of titel hebben, met de ingangsdatums. Deze tabellen moeten fijnmazige (mogelijk op kolommen gebaseerde) machtigingen hebben om te voorkomen dat de effective_from
wordt bijgewerkt datums en de werkelijke waarden zodra de record is ingevoegd.
U moet ook de bovenstaande controle-oplossing voor deze tabellen gebruiken.