Change Data Capture
データベースから行レベルの変更をストリーミングします。CDCソースはinsert、update、deleteをキャプチャし、任意で各購読者にまず既存行の一貫したスナップショットを渡し、すべてをドライバー中立の変更イベントとして配信します。ソースはエントリIDでアドレス指定でき、Luaからはcdcモジュール経由で利用します。
エントリ種別
| 種別 | 説明 |
|---|---|
db.cdc.postgres |
Postgresの論理レプリケーション(pgoutputプラグイン) |
db.cdc.sqlite |
db.sql.sqliteリソースを通じて観測されるSQLiteへの書き込み |
どちらの種別も、同じLua API、同じソース情報レコード、同じ変更イベントの形を公開します。異なるのは保証の集合であり、これはソースごとにケイパビリティとして公開されます。
Postgresの設定
- 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
| フィールド | 型 | デフォルト | 説明 |
|---|---|---|---|
host |
string | 必須 | Postgresのホスト |
port |
int | 必須 | Postgresのポート(0より大きいこと) |
database |
string | 必須 | データベース名 |
username |
string | 必須 | レプリケーションユーザー(REPLICATION権限が必要) |
password |
string | 必須 | パスワード(インラインまたは${env:NAME}) |
slot_name |
string | 必須 | 論理レプリケーションスロット名 |
publication |
string | - | Postgresのパブリケーション。tablesが空の場合は必須 |
tables |
[]string | - | キャプチャ対象のテーブル(schema.table)。省略するとパブリケーションのテーブルを使用 |
snapshot |
bool | false | 購読者ごとのスナップショット引き継ぎのエントリデフォルト |
streaming |
bool | false | ストリーミング版のpgoutputプロトコルを使用する |
temporary |
bool | false | 一時レプリケーションスロットを使用する(切断時に削除される) |
failover |
bool | false | フェイルオーバースロットモードを有効にする(temporaryと排他) |
standby_interval |
duration | 10s |
スタンバイステータスメッセージの間隔(例: 10s) |
status_interval |
duration | 30s |
サーバーへのステータス更新の間隔 |
snapshot_fetch_size |
int | 1000 | スナップショットのバッチごとに取得する行数(0以上であること) |
max_transaction_changes |
int | 1000000 | 1つのトランザクションをデコードする間にバッファリングする変更の最大数 |
max_transaction_bytes |
int | 268435456 | 1つのトランザクションをデコードする間にバッファリングする論理バイト数の最大値(256 MiB) |
max_inflight_changes |
int | 1000000 | 処理中の全トランザクションにわたって保持する変更の最大数 |
max_inflight_bytes |
int | 268435456 | 処理中の全トランザクションにわたって保持する論理バイト数の最大値(256 MiB) |
subscriptions |
object | - | 購読の受け入れ制限。購読の制限を参照 |
options |
map | - | 追加の接続オプション |
lifecycle |
object | - | ライフサイクル設定 |
いずれかのmax_*フィールドに0を指定するとデフォルトが選択されます。デコーダーが無制限になることはありません。負の値は拒否されます。
認証情報の${env:NAME}プレースホルダーは、デコード時に環境レジストリを通じて解決されます。
SQLiteの設定
SQLiteソースは自前のデータベースを開きません。既存のdb.sql.sqliteリソースを借用し、そのリソースのコミット済みミューテーションのオブザーバーを購読します。したがって、そのWippy SQLリソースを通じて行われた書き込みのみを正確にキャプチャします。別のプロセス、別のコネクション、外部ツールによる書き込みは観測されません。
- 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
| フィールド | 型 | デフォルト | 説明 |
|---|---|---|---|
db_resource |
string | 必須 | 観測対象のdb.sql.sqliteリソースのエントリID |
name |
string | - | 受け付けられるが、ソース名は常にエントリID |
tables |
[]string | - | キャプチャ対象のテーブル。省略すると全テーブル |
snapshot |
bool | false | 購読者ごとのスナップショット引き継ぎのエントリデフォルト |
status_interval |
duration | 30s |
ステータス更新の間隔 |
subscriptions |
object | - | 購読の受け入れ制限。購読の制限を参照 |
lifecycle |
object | - | ライフサイクル設定 |
ソースはSQLリソースをライフサイクル要件として宣言するため、スーパーバイザーは先にデータベースを起動し、データベースの世代が置き換えられるとソースを再起動します。
sqlite_preupdate_hookビルドタグ付きでビルドされたランタイムが必要です。公式ビルドにはこれが含まれています。タグがない場合、ドライバーはフェイルクローズドで動作します。db.cdc.sqliteエントリの作成は、何もキャプチャしないソースを起動する代わりにsqlite cdc requires the sqlite_preupdate_hook build tagを返します。
購読の制限
各ソースは限られた数の購読者を受け入れ、その最悪ケースのバックログを事前に予約します。スナップショットのスロットは、スナップショットを有効にしたストリームが閉じるまで予約されたままです。
subscriptions:
max_subscriptions: 1024
max_snapshot_subscriptions: 4
max_bytes: 268435456
| フィールド | 型 | デフォルト | 説明 |
|---|---|---|---|
max_subscriptions |
int | 1024 | ソースが受け入れる同時購読数 |
max_snapshot_subscriptions |
int | 4 | スナップショットを有効にした同時購読数 |
max_bytes |
int | 268435456 | 予約される購読者バックログの合計バイト数(256 MiB) |
0を指定するとデフォルトが選択され、負の値は拒否されます。制限を使い切ると、購読は再試行可能なerrors.UNAVAILABLEで失敗します。
仕組み
- Postgresソースはレプリケーションユーザーとして接続し、
slot_nameで指定されたスロットを作成(または再開)します。SQLiteソースはdb_resourceを借用し、そのリソースのコミット済みミューテーションのオブザーバーを購読します。 - 行の変更は、
opがinsert、update、delete、truncateのドライバー中立な変更イベントへデコードされます。 - ストリームで
snapshotが有効な購読者は(エントリのsnapshotフィールド、またはストリームのopts.snapshotにより)、まず既存行をop = "snapshot"のイベントとして受け取り、その後、両者の間に切れ目なくライブの変更へ続きます。 - Postgresソースは定期的にLSNを確認応答し、サーバーがWALセグメントを解放できるようにします(
standby_interval)。 - ソースは自身のエントリIDで登録されます。Luaコードは
cdc.streamで購読します。
ケイパビリティ
すべてのソースは自身が保証する内容を公開するため、コンシューマーはエントリ種別ではなくケイパビリティで分岐します。
| ケイパビリティ | db.cdc.postgres |
db.cdc.sqlite |
意味 |
|---|---|---|---|
snapshot |
可 | 可 | アトミックなスナップショット/ライブの引き継ぎをサポートする |
capture_resume |
可(temporaryでない場合) |
不可 | ソースの進捗が再接続をまたいで保持される |
replayable |
不可 | 不可 | 個々の購読者が過去のイベントを再生できる |
captures_external_writes |
可 | 不可 | このランタイムの外で行われた書き込みをキャプチャする |
before_images |
不可 | 可 | updateとdeleteで完全な変更前の行イメージを保証する |
coalesced |
不可 | 可 | トランザクション内で同じ行への書き込みが繰り返された場合、まとめられて到着することがある |
ケイパビリティのフラグはソースの進捗を表すものであり、永続的な配信を表すものではありません。遅れをとった、あるいは切断した個々の購読者に対してイベントを再生するドライバーはありません。
ソース情報
各ソースは情報レコードで記述され、cdc.sourceとcdc.list_sourcesが返します。
| フィールド | 型 | 説明 |
|---|---|---|
id |
string | エントリID |
kind |
string | db.cdc.postgresまたはdb.cdc.sqlite |
name |
string | ソース名(エントリID) |
state |
string | unknown、starting、running、faulted、stopped |
generation |
string | 現在のソース世代。ソースが置き換えられると変化する |
epoch |
string | generationと同じ値 |
engine |
string | エンジン名(sqlite) |
db_resource |
string | 観測対象のSQLリソースのエントリID(db.cdc.sqlite) |
slot |
string | レプリケーションスロット名(db.cdc.postgres) |
publication |
string | 設定されている場合のPostgresのパブリケーション |
tables |
[]string | 設定されている場合のキャプチャ対象テーブル |
streaming |
bool | ソースが現在稼働中かどうか |
failover |
bool | フェイルオーバースロットのモード(db.cdc.postgres) |
temporary |
bool | 一時スロット(db.cdc.postgres) |
snapshot |
bool | エントリレベルのスナップショットのデフォルト |
faulted |
bool | ソースがfaulted状態にあるかどうか |
error |
string | 記録されている場合の直近のソースエラー |
admission |
object | active、snapshots、reserved_bytes、rejected |
capabilities |
object | ケイパビリティを参照 |
admissionはキューの充填量ではなく予約を数えます。activeは受け入れられた購読数、snapshotsはそのうちスナップショットを有効にした数、reserved_bytesは予約されたバックログ予算、rejectedは制限によって拒否された購読の累計数です。
権限
| アクション | リソース | 説明 |
|---|---|---|
cdc.source |
ソースのエントリID | ソース情報を読む。cdc.list_sourcesのフィルタにも使われる |
cdc.subscribe |
ソースのエントリID | 変更ストリームを開く |
CDCの権限はデータベースへのアクセスとは別です。ソースは、変更前イメージを含め、キャプチャしたすべての行を公開しうるからです。ストリームのフィルタは配信を絞り込むだけであり、ソースへのアクセスを付与することは決してありません。
- name: cdc_reader
kind: security.policy
policy:
effect: allow
actions: [cdc.source, cdc.subscribe]
resources: [app:changes]