SQL Academy · leksjon

Hendelsestabeller med kun tillegg

Registrer det som skjedde, og overskriv aldri.

Leksjon 2 av 413 trinn

Hendelsestabeller med kun tillegg er en gratis leksjon i SQL Academy på CoddyKit. Dette er leksjon 2 av 4. Du kan lese hele leksjonen gratis nedenfor – og deretter øve praktisk i nettleseren med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i SQL Academy, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i SQL Academy inneholder totalt 4 leksjoner.

Hva er en append-only-tabell?

En append-only-hendelsestabell er en tabell der rader bare settes inn – de oppdateres eller slettes aldri. Hver rad representerer noe som skjedde på et bestemt tidspunkt.

Dette mønsteret er grunnlaget for event sourcing. I stedet for å lagre den gjeldende tilstanden lagrer du hver endring som en uforanderlig hendelse, slik at du får en fullstendig historikk som kan revideres.

Opprette en hendelsestabell

En godt utformet hendelsestabell registrerer hvem som gjorde hva, på hvilken ressurs og når. Kolonnen occurred_at registrerer det nøyaktige tidsstempelet, og DEFAULT NOW() sørger for at den alltid fylles ut automatisk.

Legg merke til at det ikke finnes noen UPDATE eller DELETE i dette designet – radene er permanente når de først er skrevet.

CREATE TABLE account_events (
  id           BIGSERIAL PRIMARY KEY,
  account_id   BIGINT      NOT NULL,
  event_type   TEXT        NOT NULL,
  payload      JSONB,
  occurred_at  TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

Sette inn hendelser

Hver handling en bruker utfører – innlogging, innskudd av penger eller endring av en e-postadresse – blir en ny rad. Du går aldri tilbake og redigerer en tidligere hendelse. Hvis noe må korrigeres, setter du i stedet inn en kompenserende hendelse.

På denne måten bevares hele hendelsesforløpet i riktig rekkefølge.

INSERT INTO account_events (account_id, event_type, payload)
VALUES
  (42, 'account_opened',  '{"plan": "free"}'),
  (42, 'email_verified',  '{"email": "alice@example.com"}'),
  (42, 'plan_upgraded',   '{"from": "free", "to": "pro"}');

Lese hele historikken

Fordi hver tilstandsendring lagres som en rad, er det enkelt å hente hele historikken for en konto med en SELECT-spørring sortert etter tid. Du kan spille av hele livsløpet til en post, fra den første hendelsen til den nyeste.

SELECT
  id,
  event_type,
  payload,
  occurred_at
FROM account_events
WHERE account_id = 42
ORDER BY occurred_at ASC;

Utlede gjeldende tilstand

Med en append-only-tabell lagrer du ikke den gjeldende tilstanden direkte – du utleder den ved å lese den nyeste relevante hendelsen. Her er den gjeldende planen for konto 42 det som den nyeste plan_upgraded- eller account_opened-hendelsen angir.

Ved å bruke ORDER BY occurred_at DESC LIMIT 1 henter du effektivt det nyeste øyeblikksbildet.

SELECT payload->>'to'  AS current_plan
FROM   account_events
WHERE  account_id = 42
  AND  event_type IN ('account_opened', 'plan_upgraded')
ORDER BY occurred_at DESC
LIMIT 1;

Håndheve uforanderlighet med regler

Append-only-garantien kan håndheves på databasenivå ved hjelp av en RULE som stille ignorerer alle UPDATE- eller DELETE-operasjoner på tabellen. Dette hindrer utilsiktede endringer fra alle applikasjoner som har skrivetilgang.

En trigger som utløser et unntak, er et enda strengere alternativ, siden den aktivt avviser operasjonen med en feil.

CREATE RULE no_update_events AS
  ON UPDATE TO account_events
  DO INSTEAD NOTHING;

CREATE RULE no_delete_events AS
  ON DELETE TO account_events
  DO INSTEAD NOTHING;

Uforanderlighet via trigger

En trigger som utløser et unntak, er strengere enn en stille regel – applikasjonen mottar en feil umiddelbart hvis den forsøker å endre en tidligere hendelse. Dermed blir feil synlige i stedet for å bli ignorert i stillhet.

CREATE OR REPLACE FUNCTION deny_event_mutation()
RETURNS TRIGGER AS $$
BEGIN
  RAISE EXCEPTION 'Event table is append-only: % is not allowed', TG_OP;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER trg_deny_event_mutation
BEFORE UPDATE OR DELETE ON account_events
FOR EACH ROW EXECUTE FUNCTION deny_event_mutation();

Telle hendelser over tid

Append-only-tabeller gjør tidsbaserte analyser enkle. Siden hver hendelse har et tidsstempel, kan du gruppere etter dag, uke eller måned uten ekstra kolonner. Eksempelet nedenfor teller hvor mange hendelser av hver type som inntraff per dag.

SELECT
  DATE_TRUNC('day', occurred_at) AS day,
  event_type,
  COUNT(*)                        AS total
FROM account_events
GROUP BY 1, 2
ORDER BY 1, 2;

Gjenopprette tilstand på et bestemt tidspunkt

En av de mest nyttige egenskapene ved en hendelseslogg er muligheten til å gjenopprette tilstanden til en post slik den var på et tidligere tidspunkt. Du trenger bare å filtrere hendelser frem til ønsket tidsstempel – ingen utvidelse for tidsreiser er nødvendig.

Dette er svært verdifullt ved feilsøking, revisjon og overholdelse av forskriftskrav.

-- What plan was account 42 on at the end of last month?
SELECT payload->>'to' AS plan_at_snapshot
FROM   account_events
WHERE  account_id = 42
  AND  event_type IN ('account_opened', 'plan_upgraded')
  AND  occurred_at <= DATE_TRUNC('month', NOW()) - INTERVAL '1 second'
ORDER BY occurred_at DESC
LIMIT 1;

Kompenserende hendelser i stedet for korrigeringer

Når en feil oppdages – for eksempel en feilaktig belastning – skal du ikke slette den feilaktige hendelsen. I stedet setter du inn en kompenserende hendelse som annullerer eller reverserer den. Begge hendelsene forblir synlige i loggen og viser nøyaktig hva som skjedde, og når korrigeringen ble gjort.

Dette holder revisjonssporet komplett og gjør det mulig å oppdage manipulering.

-- A charge was applied by mistake; record a reversal
INSERT INTO account_events (account_id, event_type, payload)
VALUES (
  42,
  'charge_reversed',
  '{"reason": "billing_error", "reverses_event_id": 17}'
);

Partisjonere store hendelsestabeller

Hendelsestabeller vokser raskt. Partisjonering etter et tidsintervall holder de enkelte partisjonene små, gjør intervallspørringer raskere og gjør det mulig å arkivere eller slette gamle partisjoner uten å berøre nyere data.

PostgreSQLs deklarative partisjonering gjør dette enkelt: definer en RANGE-partisjon på occurred_at, så lar du databasen rute innsettinger automatisk.

CREATE TABLE account_events_2025
  PARTITION OF account_events
  FOR VALUES FROM ('2025-01-01') TO ('2026-01-01');

CREATE TABLE account_events_2026
  PARTITION OF account_events
  FOR VALUES FROM ('2026-01-01') TO ('2027-01-01');

Kunnskapstest: append-only-tabeller

Test forståelsen din av utforming av append-only-hendelsestabeller.

Oppsummering: Append-only-hendelsestabeller

I denne leksjonen lærte du å utforme og bruke append-only-hendelsestabeller:

  • Uforanderlighet – rader settes inn én gang og endres aldri. Tidligere hendelser er fakta.
  • Fullstendig historikk – hver tilstandsendring bevares, noe som muliggjør fullstendige revisjonsspor og point-in-time-spørringer.
  • Kompenserende hendelser – feil korrigeres ved å legge til en ny reverserende hendelse, ikke ved å slette den gamle.
  • Håndheving – regler eller triggere på databasenivå hindrer utilsiktede endringer.
  • Skalerbarhet – intervallpartisjonering holder store hendelseslogger effektive over tid.

Append-only-tabeller er bærebjelken i event sourcing, CQRS-arkitekturer og alle systemer der muligheten til å revidere og historisk nøyaktighet er avgjørende.

Gratis å komme i gang

Lær deg SQL med en AI-veileder – gratis

Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.

Kurs
46
Leksjoner
183

Ofte stilte spørsmål

Er leksjonen «Hendelsestabeller med kun tillegg» gratis?

Ja – hele teksten i «Hendelsestabeller med kun tillegg» er gratis å lese her på nettet. For å øve interaktivt med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt, og for å låse opp resten av SQL Academy-kurset, kan du oppgradere til CoddyKit PRO. Kurset i SQL Academy inneholder totalt 4 leksjoner.

Hva lærer jeg i «Hendelsestabeller med kun tillegg»?

Registrer det som skjedde, og overskriv aldri. Du øver på SQL Academy med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.

Trenger jeg erfaring for å begynne med SQL Academy?

Ingen tidligere erfaring er nødvendig. SQL Academy på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 2 av 4.

Hvor lang tid tar leksjonen «Hendelsestabeller med kun tillegg»?

De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.

Kan jeg skrive og kjøre kode i denne SQL Academy-leksjonen?

Ja. Alle SQL Academy-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.

Alle leksjonene i dette kurset

  1. Hvorfor ta vare på historikken
  2. Hendelsestabeller med kun tillegg
  3. Temporale og versjonerte rader
  4. Gjenoppbygge tilstand fra hendelser
← Tilbake til SQL Academy