Fra og med 10.3.4 kommer MariaDB med tidsmæssige tabeller. Det er stadig en ganske usædvanlig funktion, og vi vil gerne diskutere lidt, hvad disse tabeller er, og hvad de kan være nyttige til.
For det første, hvis nogen har misforstået titlen på denne blog, taler vi her om midlertidige tabeller, ikke midlertidige tabeller, som også findes i MariaDB. De har dog noget til fælles. Tid. Midlertidige tabeller er kortvarige, midlertidige tabeller på den anden side er designet til at give adgang til data over tid. Kort sagt kan du se tidsmæssige tabeller som en versioneret tabel, der kan bruges til at få adgang til og ændre tidligere data, finde hvilke ændringer der er foretaget og hvornår. Det kan også bruges til at rulle data tilbage til et bestemt tidspunkt.
Sådan bruges tidsmæssige tabeller i MariaDB
For at oprette en tidsmæssig tabel behøver vi kun at tilføje "WITH SYSTEM VERSIONING" til CREATE TABLE-kommandoen. Hvis du vil konvertere en almindelig tabel til en tidsmæssig, kan du køre:
ALTER TABLE mytable ADD SYSTEM VERSIONING;
Dette er stort set alt. En tidsmæssig tabel vil blive oprettet, og du kan begynde at forespørge om dens data. Der er et par måder at gøre det på.
For det første kan vi bruge SELECT til at forespørge data fra et bestemt tidspunkt:
SELECT * FROM mytable FOR SYSTEM_TIME AS OF TIMESTAMP ‘2020-06-26 10:00:00’;
Du kan også lave en forespørgsel for et område:
SELECT * FROM mytable FOR SYSTEM_TIME FROM ‘2020-06-26 08:00:00’ TO ‘2020-06-26 10:00:00’;
Det er også muligt at vise alle data:
SELECT * FROM mytable FOR SYSTEM_TIME ALL;
Hvis det er nødvendigt, kan du oprette visninger fra tidsmæssige tabeller efter det samme mønster, som vi har vist ovenfor.
I betragtning af at de samme rækker muligvis ikke opdateres på alle noderne på samme tid (f.eks. forsinkelser forårsaget af replikering), hvis du ønsker at se nøjagtig den samme tilstand af data på tværs af flere slaver, kan du definere tidspunktet ved hjælp af InnoDB transaktions-id:
SELECT * FROM mytable FOR SYSTEM_TIME AS OF TRANSACTION 123;
Som standard er alle data gemt i den samme tabel, både nuværende og gamle versioner af rækkerne. Dette kan tilføje nogle overhead, når du kun forespørger efter de seneste data. Det er muligt at bruge partitioner til at reducere denne overhead ved at oprette en eller flere partitioner til at gemme historiske data og en til at gemme nyere versioner af rækkerne. Ved hjælp af partitionsbeskæring vil MariaDB derefter være i stand til at reducere mængden af data, den skal forespørge på for at komme frem til resultatet for forespørgslen:
CREATE TABLE mytable (a INT) WITH SYSTEM VERSIONING
PARTITION BY SYSTEM_TIME INTERVAL 1 WEEK (
PARTITION p0 HISTORY,
PARTITION p1 HISTORY,
PARTITION p2 HISTORY,
PARTITION pcur CURRENT
);
Du kan også bruge andre måder at partitionere det på, som for eksempel at definere antallet af rækker, der skal gemmes pr. partition.
Når vi bruger partitionering, kan vi nu anvende almindelige bedste praksisser for partitionering som datarotation ved at fjerne gamle partitioner. Hvis du ikke har oprettet partitioner, kan du stadig gøre det gennem kommandoer som:
DELETE HISTORY FROM mytable;
DELETE HISTORY FROM mytable BEFORE SYSTEM_TIME '2020-06-01 00:00:00';
Hvis det er nødvendigt, kan du ekskludere nogle af kolonnerne fra versioneringen:
CREATE TABLE mytable (
a INT,
b INT WITHOUT SYSTEM VERSIONING
) WITH SYSTEM VERSIONING;
I MariaDB 10.4 er der tilføjet en ny mulighed, applikationstidsperioder. Hvad det grundlæggende betyder er, at det i stedet for systemtid er muligt at oprette versionering baseret på to kolonner (tidsbaseret) i tabellen:
CREATE TABLE mytable (
a INT,
date1 DATE,
date2 DATE,
PERIOD FOR date_period(date1, date2));
Det er også muligt at opdatere eller slette rækker baseret på tidspunktet (OPDATERING FOR PORTION og SLET FOR PORTION). Det er også muligt at blande applikationstids- og systemtidsversionering i én tabel.
Eksempler på tidsmæssige tabeller i MariaDB
Ok, vi har diskuteret mulighederne, lad os tage et kig på nogle af de ting, vi kan gøre med tidsmæssige tabeller.
Lad os først oprette en tabel og udfylde den med nogle data:
MariaDB [(none)]> CREATE DATABASE versioned;
Query OK, 1 row affected (0.000 sec)
MariaDB [(none)]> use versioned
Database changed
MariaDB [versioned]> CREATE TABLE mytable (a INT, b INT) WITH SYSTEM VERSIONING;
Query OK, 0 rows affected (0.005 sec)
MariaDB [versioned]> INSERT INTO mytable VALUES (1,1);
Query OK, 1 row affected (0.001 sec)
MariaDB [versioned]> INSERT INTO mytable VALUES (2,1);
Query OK, 1 row affected (0.001 sec)
MariaDB [versioned]> INSERT INTO mytable VALUES (3,1);
Query OK, 1 row affected (0.000 sec)
Lad os nu opdatere et par rækker:
MariaDB [versioned]> UPDATE mytable SET b = 2 WHERE a < 3;
Query OK, 2 rows affected (0.001 sec)
Rows matched: 2 Changed: 2 Inserted: 2 Warnings: 0
Lad os nu se alle de rækker, der er gemt i tabellen:
MariaDB [versioned]> SELECT * FROM mytable FOR SYSTEM_TIME ALL ;
+------+------+
| a | b |
+------+------+
| 1 | 2 |
| 2 | 2 |
| 3 | 1 |
| 1 | 1 |
| 2 | 1 |
+------+------+
5 rows in set (0.000 sec)
Som du kan se, indeholder tabellen ikke kun aktuelle versioner af rækkerne, men også originale værdier, fra før vi opdaterede dem.
Lad os nu tjekke, hvad klokken er, og så tilføje nogle flere rækker. Vi vil se, om vi kan se den nuværende og den tidligere version.
MariaDB [versioned]> SELECT NOW();
+---------------------+
| NOW() |
+---------------------+
| 2020-06-26 11:24:55 |
+---------------------+
1 row in set (0.000 sec)
MariaDB [versioned]> INSERT INTO mytable VALUES (4,1);
Query OK, 1 row affected (0.001 sec)
MariaDB [versioned]> INSERT INTO mytable VALUES (5,1);
Query OK, 1 row affected (0.000 sec)
MariaDB [versioned]> UPDATE mytable SET b = 3 WHERE a < 2;
Query OK, 1 row affected (0.001 sec)
Rows matched: 1 Changed: 1 Inserted: 1 Warnings: 0;
Lad os nu tjekke indholdet af tabellen. Kun aktuelle versioner af rækkerne:
MariaDB [versioned]> SELECT * FROM mytable;
+------+------+
| a | b |
+------+------+
| 1 | 3 |
| 2 | 2 |
| 3 | 1 |
| 4 | 1 |
| 5 | 1 |
+------+------+
5 rows in set (0.000 sec)
Lad os så få adgang til tabellens tilstand, før vi lavede indsættelser og opdateringer:
MariaDB [versioned]> SELECT * FROM mytable FOR SYSTEM_TIME AS OF TIMESTAMP '2020-06-26 11:24:55';
+------+------+
| a | b |
+------+------+
| 2 | 2 |
| 3 | 1 |
| 1 | 2 |
+------+------+
3 rows in set (0.000 sec)
Fungerer som forventet, vi ser kun tre rækker i tabellen.
Dette korte eksempel er på ingen måde omfattende. Vi ville gerne give dig en idé om, hvordan du kan betjene de tidsmæssige borde. Anvendelser af dette er talrige. Bedre sporing af ordretilstanden i e-handel, versionering af indholdet (konfigurationsfiler, dokumenter), indsigt i tidligere data til analytiske formål.
For at gøre det klart, kan denne funktion implementeres ved hjælp af "traditionelle" tabeller, så længe du bliver ved med at indsætte rækker, ikke opdaterer dem, men administrationen er meget nemmere at udføre, når du bruger tidsmæssige tabeller.