Från och med 10.3.4 kommer MariaDB med temporala tabeller. Det är fortfarande en ganska ovanlig funktion och vi skulle vilja diskutera lite vad dessa tabeller är och vad de kan vara användbara för.
För det första, om någon har läst rubriken på den här bloggen fel, så talar vi här om temporära tabeller, inte temporära tabeller, som också finns i MariaDB. De har dock något gemensamt. Tid. Temporära tabeller är kortlivade, temporära tabeller å andra sidan är designade för att ge tillgång till data över tid. Kort sagt kan du se temporala tabeller som en versionstabell som kan användas för att komma åt och ändra tidigare data, hitta vilka ändringar som har gjorts och när. Den kan också användas för att återställa data till en viss tidpunkt.
Hur man använder temporära tabeller i MariaDB
För att skapa en temporal tabell behöver vi bara lägga till "WITH SYSTEM VERSIONING" till CREATE TABLE-kommandot. Om du vill konvertera en vanlig tabell till en temporär kan du köra:
ALTER TABLE mytable ADD SYSTEM VERSIONING;
Detta är i stort sett allt. En tidstabell kommer att skapas och du kan börja söka efter dess data. Det finns ett par sätt att göra det på.
För det första kan vi använda SELECT för att söka efter data från en viss tidpunkt:
SELECT * FROM mytable FOR SYSTEM_TIME AS OF TIMESTAMP ‘2020-06-26 10:00:00’;
Du kan också göra en fråga för ett intervall:
SELECT * FROM mytable FOR SYSTEM_TIME FROM ‘2020-06-26 08:00:00’ TO ‘2020-06-26 10:00:00’;
Det är också möjligt att visa all data:
SELECT * FROM mytable FOR SYSTEM_TIME ALL;
Om det behövs kan du skapa vyer från tidstabeller, enligt samma mönster som vi har visat ovan.
Med tanke på att samma rader kanske inte uppdateras på alla noder samtidigt (till exempel förseningar orsakade av replikering), om du vill se exakt samma tillstånd för data över flera slavar, kan du definiera tidpunkten med InnoDB transaktions-id:
SELECT * FROM mytable FOR SYSTEM_TIME AS OF TRANSACTION 123;
Som standard lagras all data i samma tabell, både nuvarande och gamla versioner av raderna. Detta kan lägga till lite overhead när du bara frågar efter de senaste uppgifterna. Det är möjligt att använda partitioner för att minska denna overhead genom att skapa en eller flera partitioner för att lagra historisk data och en för att lagra senaste versioner av raderna. Sedan, med hjälp av partitionsbeskärning, kommer MariaDB att kunna minska mängden data som den måste fråga för att komma fram till resultatet för frågan:
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 också använda andra sätt att partitionera den, som till exempel att definiera antalet rader som ska lagras per partition.
När vi använder partitionering kan vi nu tillämpa vanliga bästa metoder för partitionering som datarotation genom att ta bort gamla partitioner. Om du inte skapade partitioner kan du fortfarande göra det genom kommandon som:
DELETE HISTORY FROM mytable;
DELETE HISTORY FROM mytable BEFORE SYSTEM_TIME '2020-06-01 00:00:00';
Om det behövs kan du utesluta några av kolumnerna från versionshanteringen:
CREATE TABLE mytable (
a INT,
b INT WITHOUT SYSTEM VERSIONING
) WITH SYSTEM VERSIONING;
I MariaDB 10.4 har ett nytt alternativ lagts till, ansökningstidsperioder. Vad det betyder är i princip att istället för systemtid är det möjligt att skapa versionshantering baserat på två kolumner (tidsbaserad) i tabellen:
CREATE TABLE mytable (
a INT,
date1 DATE,
date2 DATE,
PERIOD FOR date_period(date1, date2));
Det är också möjligt att uppdatera eller ta bort rader baserat på tiden (UPPDATERA FÖR PORTION och DELETE FOR PORTION). Det är också möjligt att blanda applikationstid och systemtid versionering i en tabell.
Exempel på temporära tabeller i MariaDB
Ok, vi har diskuterat möjligheterna, låt oss ta en titt på några saker vi kan göra med tidstabeller.
Låt oss först skapa en tabell och fylla i den med lite 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)
Låt oss nu uppdatera några rader:
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
Låt oss nu se alla rader som är lagrade 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 innehåller tabellen inte bara aktuella versioner av raderna utan också ursprungliga värden, från innan vi uppdaterade dem.
Nu ska vi kolla vad klockan är och sedan lägga till några fler rader. Vi ska se om vi kan se nuvarande och tidigare versioner.
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;
Låt oss nu kontrollera innehållet i tabellen. Endast aktuella versioner av raderna:
MariaDB [versioned]> SELECT * FROM mytable;
+------+------+
| a | b |
+------+------+
| 1 | 3 |
| 2 | 2 |
| 3 | 1 |
| 4 | 1 |
| 5 | 1 |
+------+------+
5 rows in set (0.000 sec)
Låt oss sedan komma åt tabellens tillstånd innan vi gjorde infogningar och uppdateringar:
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)
Fungerar som förväntat, vi ser bara tre rader i tabellen.
Detta korta exempel är inte på något sätt omfattande. Vi ville ge dig en uppfattning om hur du kan använda de tidsmässiga tabellerna. Tillämpningar av detta är många. Bättre spårning av beställningens tillstånd inom e-handel, versionering av innehållet (konfigurationsfiler, dokument), insikt i tidigare data för analytiska ändamål.
För att göra det tydligt kan den här funktionen implementeras med hjälp av "traditionella" tabeller, så länge du fortsätter att infoga rader, inte uppdaterar dem, men hanteringen är mycket lättare att göra när du använder temporala tabeller.