Dine revisionsdata skal gemmes pr. tabel i stedet for alle på ét sted. Det, du skal gøre, er at oprette en revisionstabel for hver af de tabeller, du vil spore, og oprette triggere for at oprette en post i revisionstabellen for enhver datamanipulationshandling på den reviderede tabel.
Det er absolut tilrådeligt at afvise DELETE
handlinger på items
og item_options
tabeller - tilføj flag som item_active
og item_option_active
så du kan softdelete dem i stedet for. Dette er normal praksis i situationer, hvor du gør ting som at gemme fakturaer, der refererer til produkter, der er bestilt i fortiden, og har brug for dataene til historiske rapporteringsformål, men ikke til daglig brug.
Dine revisionstabeller er ikke noget, du skal bruge til at referere til gamle data, din normale datamodel skal understøtte blot at "skjule" gamle data, hvor det er sandsynligt, at det stadig vil blive brugt, og gemme flere versioner af data, der vil ændre sig over tid.
Til revision er det også nyttigt at gemme brugernavnet på den sidste bruger til at ændre en given post - når det bruges fra en webapplikation, kan du ikke bruge MySQL's USER()
funktion for at få brugbar information om, hvem der er logget på. Tilføjelse af en kolonne og udfyldning af den betyder, at du kan bruge disse oplysninger i dine revisionstriggere.
NB: Jeg går ud fra, at du ikke vil tillade, at vare-id'er ændres under normale forhold - det ville gøre dit revisionssystem mere komplekst.
Hvis du tilføjer aktive flag og sidst ændrede data til dine tabeller, vil de se nogenlunde sådan ud:
Tabel med elementer:
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 med vareindstillinger:
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 | |
+---------------+--------------+------+-----+---------+----------------+
Dine revisionstabeller skal gemme fire ekstra stykker information:
- Revisions-id - dette id er kun unikt for historien om dette tabel, er det ikke en global værdi
- Ændring foretaget af - databasebrugeren, der foretog ændringen
- Skift dato/klokkeslæt
- Handlingstype -
INSERT
ellerUPDATE
(ellerDELETE
hvis du tillod det)
Dine revisionstabeller skal se nogenlunde sådan ud:
Revisionstabel for elementer:
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 | |
+------------------+--------------+------+-----+---------+----------------+
Revisionstabel for vareindstillinger:
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 | |
+---------------+--------------+------+-----+---------+----------------+
Brug ikke fremmednøgler på dine revisionstabeller; rækkerne i revisionstabellerne er ikke underordnede rækker af de poster, de reviderer, så fremmednøgler er ikke til nogen nytte.
Udløsere
NB: MySQL understøtter ikke triggere af flere sætninger, så du skal bruge en for hver af INSERT
, UPDATE
og DELETE
(hvis relevant).
Dine triggere skal blot INSERT
alt det NEW
værdier i revisionstabellen. Udløserdefinitionerne for items
tabellen kan være:
/* 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;
Opret lignende triggere for item_options
tabel.
Opdatering:Datahistorik i e-handel
Den revision, vi foretog ovenfor, giver dig mulighed for at opbevare en historik for enhver given databasetabel, men skaber et datalager, der ikke er egnet til brug for data, der skal tilgås regelmæssigt.
I et e-handelssystem holdes brugelig historiske data er vigtige, så du kan ændre attributter, mens du stadig præsenterer gamle værdier i visse situationer.
Dette bør være fuldstændig adskilt fra din revisionsløsning
Den bedste måde at gemme historik på er at oprette en historiktabel for hver attribut som skal opbevares historisk. Dette Stackoverflow-spørgsmål har nogle gode oplysninger om at opbevare en historik for en given egenskab .
I din situation, hvis du kun er bekymret for pris og titel, ville du oprette en prices
tabel og en item_titles
bord. Hver enkelt vil have en fremmednøgle til enten item_options
tabellen eller items
tabel (mastertabellerne ville stadig gemme den aktuelle pris eller titel), og vil have prisen eller titlen med dens ikrafttrædelsesdatoer. Disse tabeller bør have finkornede (muligvis kolonnebaserede) tilladelser for at undgå opdatering af effective_from
datoer og de faktiske værdier, når posten er indsat.
Du bør også bruge revisionsløsningen ovenfor på disse tabeller.