sql >> Database >  >> RDS >> Mysql

Audit logging voor productgegevens?

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 of UPDATE (of DELETE 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.



  1. Hoe kan ik alleen in een database invoegen als een waarde is gewijzigd?

  2. Rails 3, ActiveRecord, PostgreSQL - .uniq-opdracht werkt niet?

  3. Mysql-database importeren met Ruby/Chef Recipe for Vagrant

  4. JPA werkt kolom niet bij met Converter-klasse