0Pricing
SQL Academy · Lektion

Eventtabellen mit ausschließlichem Anhängen

Zeichnen Sie auf, was passiert ist, und überschreiben Sie nie Daten

Eventtabellen mit ausschließlichem Anhängen ist eine kostenlose SQL Academy-Lektion auf CoddyKit. Dies ist Lektion 2 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des SQL Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der SQL Academy-Kurs umfasst insgesamt 4 Lektionen.

Was ist eine Append-only-Tabelle?

Eine Append-only-Ereignistabelle ist eine Tabelle, in die Zeilen ausschließlich eingefügt — niemals aktualisiert oder gelöscht — werden. Jede Zeile steht für etwas, das zu einem bestimmten Zeitpunkt geschehen ist.

Dieses Muster bildet die Grundlage von Event Sourcing. Statt den aktuellen Zustand zu speichern, speichern Sie jede Änderung als unveränderliches Ereignis. So erhalten Sie eine vollständige, prüfbare Historie.

Eine Ereignistabelle erstellen

Eine gut entworfene Ereignistabelle erfasst, wer was an welcher Ressource und wann getan hat. Die Spalte occurred_at speichert den exakten Zeitstempel, und DEFAULT NOW() stellt sicher, dass sie immer automatisch ausgefüllt wird.

Beachten Sie, dass dieses Design kein UPDATE oder DELETE enthält — sobald Zeilen geschrieben wurden, sind sie dauerhaft.

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

Ereignisse einfügen

Jede Aktion eines Benutzers — sich anmelden, Geld einzahlen, eine E-Mail-Adresse ändern — wird zu einer neuen Zeile. Sie gehen niemals zurück und bearbeiten ein früheres Ereignis. Wenn etwas korrigiert werden muss, fügen Sie stattdessen ein kompensierendes Ereignis ein.

So bleibt die vollständige Abfolge der Ereignisse in der richtigen Reihenfolge erhalten.

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

Die vollständige Historie lesen

Da jede Zustandsänderung als Zeile gespeichert wird, ist das Abfragen der vollständigen Historie eines Kontos mit einem zeitlich sortierten SELECT ganz einfach. Sie können den gesamten Lebenszyklus eines Datensatzes vom ersten bis zum aktuellsten Ereignis wiedergeben.

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

Den aktuellen Zustand ableiten

In einer Append-only-Tabelle speichern Sie den aktuellen Zustand nicht direkt — Sie leiten ihn ab, indem Sie das letzte relevante Ereignis lesen. Hier entspricht der aktuelle Plan für Konto 42 dem Inhalt des neuesten Ereignisses plan_upgraded oder account_opened.

Mit ORDER BY occurred_at DESC LIMIT 1 rufen Sie die aktuellste Momentaufnahme effizient ab.

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;

Unveränderlichkeit mit Regeln erzwingen

Die Append-only-Garantie lässt sich auf Datenbankebene mit einer RULE erzwingen, die jedes UPDATE oder DELETE auf der Tabelle stillschweigend ignoriert. Dadurch werden versehentliche Änderungen durch jede Anwendung verhindert, die Schreibzugriff besitzt.

Ein Trigger, der eine Exception auslöst, ist eine noch strengere Alternative, da er den Vorgang aktiv mit einem Fehler ablehnt.

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;

Unveränderlichkeit per Trigger

Ein Trigger, der eine Exception auslöst, ist strenger als eine stille Regel — die Anwendung erhält sofort einen Fehler, wenn sie versucht, ein früheres Ereignis zu verändern. Dadurch werden Fehler sichtbar, statt stillschweigend verschluckt zu werden.

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

Ereignisse im Zeitverlauf zählen

Append-only-Tabellen machen zeitbezogene Analysen unkompliziert. Da jedes Ereignis einen Zeitstempel besitzt, können Sie ohne zusätzliche Spalten nach Tag, Woche oder Monat gruppieren. Das folgende Beispiel zählt, wie viele Ereignisse jedes Typs pro Tag aufgetreten sind.

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

Rekonstruktion zu einem bestimmten Zeitpunkt

Eine der leistungsfähigsten Eigenschaften eines Ereignisprotokolls ist die Möglichkeit, den Zustand jedes Datensatzes so zu rekonstruieren, wie er zu einem früheren Zeitpunkt bestand. Filtern Sie einfach alle Ereignisse bis zum gewünschten Zeitstempel — eine Time-Travel-Erweiterung ist nicht erforderlich.

Das ist für das Debugging, Audits und die Einhaltung gesetzlicher Vorschriften äußerst wertvoll.

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

Kompensierende Ereignisse statt Korrekturen

Wenn ein Fehler entdeckt wird — beispielsweise eine falsche Belastung —, löschen Sie das fehlerhafte Ereignis nicht. Fügen Sie stattdessen ein kompensierendes Ereignis ein, das die Belastung aufhebt oder rückgängig macht. Beide Ereignisse bleiben im Protokoll sichtbar und zeigen genau, was wann geschehen ist und wann die Korrektur vorgenommen wurde.

So bleibt der Audit-Trail vollständig und manipulationssicher.

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

Große Ereignistabellen partitionieren

Ereignistabellen wachsen schnell. Eine Partitionierung nach Zeitbereichen hält einzelne Partitionen klein, beschleunigt Bereichsabfragen und ermöglicht es, alte Partitionen zu archivieren oder zu löschen, ohne aktuelle Daten anzufassen.

Die deklarative Partitionierung von PostgreSQL macht dies unkompliziert: Definieren Sie eine RANGE-Partition für occurred_at, und die Datenbank leitet Einfügungen automatisch weiter.

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

Wissenscheck zu Append-only-Tabellen

Testen Sie Ihr Verständnis des Entwurfs von Append-only-Ereignistabellen.

Zusammenfassung: Append-only-Ereignistabellen

In dieser Lektion haben Sie gelernt, wie Sie Append-only-Ereignistabellen entwerfen und verwenden:

  • Unveränderlichkeit — Zeilen werden einmal eingefügt und nie verändert. Frühere Ereignisse sind Fakten.
  • Vollständige Historie — Jede Zustandsänderung bleibt erhalten und ermöglicht vollständige Audit-Trails sowie Stichtagsabfragen.
  • Kompensierende Ereignisse — Fehler werden durch das Hinzufügen eines neuen Umkehrereignisses korrigiert, nicht durch das Löschen des alten Ereignisses.
  • Erzwingung — Regeln oder Trigger auf Datenbankebene verhindern versehentliche Änderungen.
  • Skalierbarkeit — Eine Bereichspartitionierung sorgt dafür, dass große Ereignisprotokolle auch im Laufe der Zeit performant bleiben.

Append-only-Tabellen bilden das Rückgrat von Event Sourcing, CQRS-Architekturen und allen Systemen, in denen Prüfbarkeit und historische Genauigkeit entscheidend sind.

Häufig gestellte Fragen

Ist die Lektion „Eventtabellen mit ausschließlichem Anhängen“ kostenlos?

Ja — der vollständige Text von „Eventtabellen mit ausschließlichem Anhängen“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des SQL Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der SQL Academy-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „Eventtabellen mit ausschließlichem Anhängen“?

Zeichnen Sie auf, was passiert ist, und überschreiben Sie nie Daten Du übst SQL Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um SQL Academy zu starten?

Keine Vorkenntnisse erforderlich. SQL Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 2 von 4.

Wie lange dauert die Lektion „Eventtabellen mit ausschließlichem Anhängen“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser SQL Academy-Lektion Code schreiben und ausführen?

Ja. Jede SQL Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. Warum Sie den Verlauf speichern sollten
  2. Eventtabellen mit ausschließlichem Anhängen
  3. Temporale und versionierte Zeilen
  4. Zustand aus Events rekonstruieren
← Zurück zu SQL Academy