SQL Academy · Oppitunti

Vain lisäykseen perustuvat tapahtumataulut

Tallenna tapahtumat äläkä koskaan ylikirjoita niitä.

Oppitunti 2/413 vaihetta

Vain lisäykseen perustuvat tapahtumataulut on ilmainen SQL Academy-oppitunti CoddyKitissä. Tämä on oppitunti 2/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu SQL Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. SQL Academy-kurssilla on yhteensä 4 oppituntia.

Mikä on vain lisäyksiä salliva taulu?

Vain lisäyksiä salliva tapahtumataulu on taulu, johon lisätään rivejä, mutta rivejä ei koskaan päivitetä tai poisteta. Jokainen rivi kuvaa jotakin, joka tapahtui tiettynä ajankohtana.

Tämä malli on event sourcingin perusta. Nykyisen tilan tallentamisen sijaan jokainen muutos tallennetaan muuttumattomana tapahtumana, jolloin käytettävissä on täydellinen ja auditoitava historia.

Tapahtumataulun luominen

Hyvin suunniteltu tapahtumataulu tallentaa tiedot siitä, kuka teki mitä, mille resurssille ja milloin. occurred_at-sarake tallentaa tarkan aikaleiman, ja DEFAULT NOW() varmistaa, että se täytetään aina automaattisesti.

Huomaatte, ettei tässä rakenteessa ole UPDATE- tai DELETE-operaatioita — rivit ovat pysyviä, kun ne on kerran kirjoitettu.

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()
);

Tapahtumien lisääminen

Jokainen käyttäjän toiminto — kirjautuminen, rahan tallettaminen tai sähköpostiosoitteen muuttaminen — muuttuu uudeksi riviksi. Aiempiin tapahtumiin ei koskaan palata muokkaamaan. Jos jokin on korjattava, lisäätte sen sijaan kumoavan tapahtuman.

Näin koko tapahtumaketju säilyy siinä järjestyksessä, jossa tapahtumat tapahtuivat.

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"}');

Koko historian lukeminen

Koska jokainen tilanmuutos tallennetaan omana rivinään, tilin koko historian kysely on yksinkertainen ajan mukaan järjestetty SELECT. Voitte toistaa tietueen koko elinkaaren ensimmäisestä tapahtumasta uusimpaan.

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

Nykyisen tilan johtaminen

Vain lisäyksiä sallivassa taulussa nykyistä tilaa ei tallenneta suoraan, vaan se johdetaan lukemalla viimeisin asiaankuuluva tapahtuma. Tässä tilin 42 nykyinen paketti on se, minkä viimeisin plan_upgraded- tai account_opened-tapahtuma ilmoittaa.

Ilmaus ORDER BY occurred_at DESC LIMIT 1 hakee uusimman tilannekuvan tehokkaasti.

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;

Muuttumattomuuden varmistaminen säännöillä

Vain lisäyksiä salliva ominaisuus voidaan varmistaa tietokantatasolla käyttämällä RULE-sääntöä, joka ohittaa äänettömästi kaikki tauluun kohdistuvat UPDATE- ja DELETE-operaatiot. Tämä estää tahattomat muutokset kaikissa sovelluksissa, joilla on kirjoitusoikeus.

Poikkeuksen nostava triggeri on vielä vahvempi vaihtoehto, sillä se hylkää operaation aktiivisesti ja palauttaa virheen.

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;

Muuttumattomuus triggerillä

Poikkeuksen nostava triggeri on tiukempi kuin äänetön sääntö — sovellus saa virheen välittömästi, jos se yrittää muuttaa aiempaa tapahtumaa. Näin virheet tulevat näkyviin sen sijaan, että ne ohitettaisiin äänettömästi.

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();

Tapahtumien laskeminen ajan mittaan

Vain lisäyksiä sallivat taulut tekevät aikaperusteisesta analytiikasta suoraviivaista. Koska jokaisella tapahtumalla on aikaleima, voitte ryhmitellä tapahtumat päivän, viikon tai kuukauden mukaan ilman ylimääräisiä sarakkeita. Alla oleva esimerkki laskee, kuinka monta kunkin tyyppistä tapahtumaa tapahtui päivittäin.

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

Tilanteen rekonstruointi tiettynä ajankohtana

Yksi tapahtumalokin tehokkaimmista ominaisuuksista on mahdollisuus rekonstruoida minkä tahansa tietueen tila sellaisena kuin se oli menneenä ajankohtana. Suodattakaa tapahtumat yksinkertaisesti haluttuun aikaleimaan asti — aikamatkailulaajennusta ei tarvita.

Tämä on erittäin hyödyllistä virheenkorjauksessa, auditoinneissa ja sääntelyn noudattamisessa.

-- 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;

Korjaavien tapahtumien käyttäminen korjausten sijaan

Kun virhe havaitaan — esimerkiksi virheellinen veloitus — virheellistä tapahtumaa ei poisteta. Sen sijaan lisäätte korjaavan tapahtuman, joka kumoaa tai peruuttaa sen. Molemmat tapahtumat säilyvät lokissa, joten siitä näkyy täsmällisesti, mitä tapahtui ja milloin korjaus tehtiin.

Näin auditointipolku säilyy täydellisenä ja peukaloinnin paljastavana.

-- 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}'
);

Suurten tapahtumataulujen osiointi

Tapahtumataulut kasvavat nopeasti. Aikavälin mukaan osiointi pitää yksittäiset osiot pieninä, nopeuttaa välikyselyitä ja mahdollistaa vanhojen osioiden arkistoinnin tai poistamisen koskematta tuoreisiin tietoihin.

PostgreSQL:n deklaratiivinen osiointi tekee tästä suoraviivaista: määritelkää RANGE-osiointi occurred_at-sarakkeelle ja antakaa tietokannan ohjata lisäykset automaattisesti.

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');

Vain lisäyksiä sallivien taulujen tietotesti

Testatkaa ymmärrystänne vain lisäyksiä sallivien tapahtumataulujen suunnittelusta.

Kertaus: vain lisäyksiä sallivat tapahtumataulut

Tässä oppitunnissa opitte suunnittelemaan ja käyttämään vain lisäyksiä sallivia tapahtumatauluja:

  • Muuttumattomuus — rivit lisätään kerran, eikä niitä koskaan muuteta. Aiemmat tapahtumat ovat tosiasioita.
  • Täydellinen historia — jokainen tilanmuutos säilytetään, mikä mahdollistaa täydelliset auditointipolut ja ajankohtakyselyt.
  • Korjaavat tapahtumat — virheet korjataan lisäämällä uusi kumoava tapahtuma, ei poistamalla vanhaa.
  • Valvonta — tietokantatason säännöt tai triggerit estävät tahattomat muutokset.
  • Skaalautuvuus — aikavälin mukaan tehty osiointi pitää suuret tapahtumalokit suorituskykyisinä ajan mittaan.

Vain lisäyksiä sallivat taulut ovat event sourcingin, CQRS-arkkitehtuurien ja kaikkien auditoinnin sekä historian tarkkuuden kannalta kriittisten järjestelmien selkäranka.

Aloita maksutta

Opi SQL tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
46
Oppitunnit
183

Usein kysytyt kysymykset

Onko oppitunti ”Vain lisäykseen perustuvat tapahtumataulut” ilmainen?

Kyllä – oppitunnin ”Vain lisäykseen perustuvat tapahtumataulut” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko SQL Academy-kurssin, päivitä CoddyKit PROhon. SQL Academy-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”Vain lisäykseen perustuvat tapahtumataulut”?

Tallenna tapahtumat äläkä koskaan ylikirjoita niitä. Harjoittelet SQL Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni SQL Academy-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin SQL Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 2/4.

Kuinka kauan ”Vain lisäykseen perustuvat tapahtumataulut”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä SQL Academy-oppitunnilla?

Kyllä. Jokainen SQL Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. Miksi historia kannattaa säilyttää
  2. Vain lisäykseen perustuvat tapahtumataulut
  3. Ajalliset ja versioidut rivit
  4. Tilanteen uudelleenrakentaminen tapahtumista
← Takaisin: SQL Academy