Change Data Capture
Streamen Sie zeilenbezogene Änderungen aus einer Datenbank. Eine CDC-Quelle erfasst Inserts, Updates und Deletes, übergibt jedem Abonnenten optional zuerst einen konsistenten Snapshot der vorhandenen Zeilen und liefert alles als treiberneutrale Änderungsereignisse. Quellen sind über ihre Entry-ID adressierbar und werden aus Lua über das cdc-Modul konsumiert.
Entry-Typen
| Kind | Beschreibung |
|---|---|
db.cdc.postgres |
Logische Postgres-Replikation (Plugin pgoutput) |
db.cdc.sqlite |
SQLite-Schreibvorgänge, beobachtet über eine db.sql.sqlite-Ressource |
Beide Kinds stellen dieselbe Lua-API, denselben Quellinformations-Datensatz und dieselbe Form von Änderungsereignissen bereit. Was sich unterscheidet, ist die Menge der Garantien, veröffentlicht pro Quelle als Capabilities.
Postgres-Konfiguration
- name: pg_cdc
kind: db.cdc.postgres
host: ${env:DB_HOST}
port: 5432
database: app
username: ${env:DB_USER}
password: ${env:app.secrets:db_password}
slot_name: wippy_slot
publication: wippy_pub
tables:
- public.users
- public.orders
snapshot: true
streaming: true
standby_interval: "10s"
status_interval: "10s"
lifecycle:
auto_start: true
| Feld | Typ | Standard | Beschreibung |
|---|---|---|---|
host |
string | erforderlich | Postgres-Host |
port |
int | erforderlich | Postgres-Port (muss > 0 sein) |
database |
string | erforderlich | Datenbankname |
username |
string | erforderlich | Replikationsbenutzer (benötigt das Recht REPLICATION) |
password |
string | erforderlich | Passwort (inline oder ${env:NAME}) |
slot_name |
string | erforderlich | Name des logischen Replikations-Slots |
publication |
string | - | Postgres-Publication; erforderlich, wenn tables leer ist |
tables |
[]string | - | Zu erfassende Tabellen (schema.table); weglassen, um die Tabellen der Publication zu verwenden |
snapshot |
bool | false | Standard des Eintrags für die Snapshot-Übergabe pro Abonnent |
streaming |
bool | false | Die Streaming-Protokollversion von pgoutput verwenden |
temporary |
bool | false | Einen temporären Replikations-Slot verwenden (beim Trennen entfernt) |
failover |
bool | false | Failover-Slot-Modus aktivieren (schließt sich mit temporary gegenseitig aus) |
standby_interval |
duration | 10s |
Intervall der Standby-Statusnachrichten (z. B. 10s) |
status_interval |
duration | 30s |
Intervall der Statusaktualisierungen an den Server |
snapshot_fetch_size |
int | 1000 | Pro Snapshot-Batch geholte Zeilen (muss >= 0 sein) |
max_transaction_changes |
int | 1000000 | Maximale Anzahl gepufferter Änderungen beim Dekodieren einer Transaktion |
max_transaction_bytes |
int | 268435456 | Maximale logische Bytes, die beim Dekodieren einer Transaktion gepuffert werden (256 MiB) |
max_inflight_changes |
int | 1000000 | Maximale Anzahl von Änderungen über alle laufenden Transaktionen hinweg |
max_inflight_bytes |
int | 268435456 | Maximale logische Bytes über alle laufenden Transaktionen hinweg (256 MiB) |
subscriptions |
object | - | Zulassungsgrenzen für Abonnements, siehe Abonnementgrenzen |
options |
map | - | Zusätzliche Verbindungsoptionen |
lifecycle |
object | - | Lebenszykluskonfiguration |
Eine Null in einem beliebigen max_*-Feld wählt den Standardwert; der Decoder ist nie unbegrenzt. Negative Werte werden abgelehnt.
Zugangsdaten lösen ${env:NAME}-Platzhalter beim Dekodieren über die Environment-Registry auf.
SQLite-Konfiguration
Eine SQLite-Quelle öffnet keine eigene Datenbank. Sie leiht sich eine vorhandene db.sql.sqlite-Ressource und abonniert deren Beobachter für committete Mutationen, erfasst also genau die Schreibvorgänge, die über diese Wippy-SQL-Ressource erfolgen — Schreibvorgänge eines anderen Prozesses, einer anderen Verbindung oder eines externen Werkzeugs werden nicht beobachtet.
- name: cdcdb
kind: db.sql.sqlite
file: /var/data/app.db
lifecycle:
auto_start: true
- name: changes
kind: db.cdc.sqlite
db_resource: app:cdcdb
tables:
- users
- orders
snapshot: true
status_interval: "30s"
lifecycle:
auto_start: true
| Feld | Typ | Standard | Beschreibung |
|---|---|---|---|
db_resource |
string | erforderlich | Entry-ID der zu beobachtenden db.sql.sqlite-Ressource |
name |
string | - | Wird akzeptiert; der Quellname ist immer die Entry-ID |
tables |
[]string | - | Zu erfassende Tabellen; weglassen für alle Tabellen |
snapshot |
bool | false | Standard des Eintrags für die Snapshot-Übergabe pro Abonnent |
status_interval |
duration | 30s |
Intervall der Statusaktualisierungen |
subscriptions |
object | - | Zulassungsgrenzen für Abonnements, siehe Abonnementgrenzen |
lifecycle |
object | - | Lebenszykluskonfiguration |
Die Quelle deklariert die SQL-Ressource als Lebenszyklus-Anforderung, sodass der Supervisor die Datenbank zuerst startet und die Quelle neu startet, wenn die Datenbankgeneration ersetzt wird.
sqlite_preupdate_hook gebaut wurde. Offizielle Builds enthalten es. Ohne das Tag scheitert der Treiber fail-closed: Das Erstellen eines db.cdc.sqlite-Eintrags gibt sqlite cdc requires the sqlite_preupdate_hook build tag zurück, statt eine Quelle zu starten, die nichts erfasst.
Abonnementgrenzen
Jede Quelle lässt eine begrenzte Anzahl von Abonnenten zu und reserviert deren Worst-Case-Rückstand im Voraus. Ein Snapshot-Slot bleibt reserviert, bis der snapshot-fähige Stream geschlossen wird.
subscriptions:
max_subscriptions: 1024
max_snapshot_subscriptions: 4
max_bytes: 268435456
| Feld | Typ | Standard | Beschreibung |
|---|---|---|---|
max_subscriptions |
int | 1024 | Von der Quelle zugelassene gleichzeitige Abonnements |
max_snapshot_subscriptions |
int | 4 | Gleichzeitige snapshot-fähige Abonnements |
max_bytes |
int | 268435456 | Insgesamt reservierte Rückstands-Bytes der Abonnenten (256 MiB) |
Null wählt den Standardwert; negative Werte werden abgelehnt. Das Ausschöpfen einer Grenze lässt das Abonnement mit einem wiederholbaren errors.UNAVAILABLE scheitern.
Funktionsweise
- Eine Postgres-Quelle verbindet sich als Replikationsbenutzer und erstellt (oder setzt fort) den in
slot_namebenannten Slot. Eine SQLite-Quelle leiht sich ihredb_resourceund abonniert deren Beobachter für committete Mutationen. - Zeilenänderungen werden in treiberneutrale Änderungsereignisse mit
opgleichinsert,update,deleteodertruncatedekodiert. - Ein Abonnent, dessen Stream
snapshotaktiviert hat — über das Feldsnapshotdes Eintrags oder überopts.snapshotam Stream — erhält zuerst die vorhandenen Zeilen als Ereignisse mitop = "snapshot"und setzt dann ohne Lücke zwischen beiden mit Live-Änderungen fort. - Eine Postgres-Quelle bestätigt regelmäßig die LSN, damit der Server WAL-Segmente freigeben kann (
standby_interval). - Die Quelle registriert sich unter ihrer Entry-ID; Lua-Code abonniert mit
cdc.stream.
Capabilities
Jede Quelle veröffentlicht, was sie garantiert, sodass Konsumenten über Capabilities verzweigen statt über den Entry-Typ.
| Capability | db.cdc.postgres |
db.cdc.sqlite |
Bedeutung |
|---|---|---|---|
snapshot |
ja | ja | Unterstützt die atomare Snapshot-/Live-Übergabe |
capture_resume |
ja, außer bei temporary |
nein | Der Fortschritt der Quelle übersteht ein erneutes Verbinden |
replayable |
nein | nein | Einzelne Abonnenten können vergangene Ereignisse erneut abspielen |
captures_external_writes |
ja | nein | Erfasst Schreibvorgänge außerhalb dieser Laufzeit |
before_images |
nein | ja | Garantiert ein vollständiges Zeilenabbild vor der Änderung bei update und delete |
coalesced |
nein | ja | Wiederholte Schreibvorgänge auf eine Zeile innerhalb einer Transaktion können zusammengefasst eintreffen |
Capability-Flags beschreiben den Fortschritt der Quelle, nicht dauerhafte Zustellung: Kein Treiber spielt Ereignisse für einen einzelnen Abonnenten erneut ab, der zurückgefallen ist oder die Verbindung verloren hat.
Quellinformationen
Jede Quelle wird durch einen Info-Datensatz beschrieben, den cdc.source und cdc.list_sources zurückgeben.
| Feld | Typ | Beschreibung |
|---|---|---|
id |
string | Entry-ID |
kind |
string | db.cdc.postgres oder db.cdc.sqlite |
name |
string | Quellname (die Entry-ID) |
state |
string | unknown, starting, running, faulted oder stopped |
generation |
string | Aktuelle Quellgeneration; ändert sich, wenn die Quelle ersetzt wird |
epoch |
string | Derselbe Wert wie generation |
engine |
string | Engine-Name (sqlite) |
db_resource |
string | Entry-ID der beobachteten SQL-Ressource (db.cdc.sqlite) |
slot |
string | Name des Replikations-Slots (db.cdc.postgres) |
publication |
string | Postgres-Publication, sofern konfiguriert |
tables |
[]string | Erfasste Tabellen, sofern konfiguriert |
streaming |
bool | Ob die Quelle derzeit läuft |
failover |
bool | Failover-Slot-Modus (db.cdc.postgres) |
temporary |
bool | Temporärer Slot (db.cdc.postgres) |
snapshot |
bool | Snapshot-Standard auf Eintragsebene |
faulted |
bool | Ob die Quelle im Zustand faulted ist |
error |
string | Letzter Quellfehler, sofern einer aufgezeichnet ist |
admission |
object | active, snapshots, reserved_bytes, rejected |
capabilities |
object | Siehe Capabilities |
admission zählt Reservierungen, nicht die Warteschlangenfüllung: active ist die Anzahl zugelassener Abonnements, snapshots die snapshot-fähige Teilmenge, reserved_bytes das reservierte Rückstandsbudget und rejected die kumulierte Anzahl der von den Grenzwerten abgelehnten Abonnements.
Berechtigungen
| Aktion | Ressource | Beschreibung |
|---|---|---|
cdc.source |
Entry-ID der Quelle | Quellinformationen lesen; filtert außerdem cdc.list_sources |
cdc.subscribe |
Entry-ID der Quelle | Einen Änderungs-Stream öffnen |
CDC-Autorität ist von Datenbankzugriff getrennt: Eine Quelle kann jede erfasste Zeile offenlegen, einschließlich der Abbilder vor der Änderung. Stream-Filter schränken nur die Zustellung ein; sie gewähren nie Zugriff auf eine Quelle.
- name: cdc_reader
kind: security.policy
policy:
effect: allow
actions: [cdc.source, cdc.subscribe]
resources: [app:changes]
Siehe auch
- CDC-Modul - Lua-Streaming-API
- Datenbank - SQL-Datenbankdienste
- Environment - Zugangsdaten über
${env:NAME}auflösen - Sicherheit - Richtlinien und Aktionen