CDC

db.cdc.postgres와 db.cdc.sqlite 소스의 변경 데이터 캡처(Change Data Capture) 스트림을 구독합니다. 구성된 소스를 나열하고, 스트림을 열고, 행 수준 변경 이벤트를 채널로 수신합니다. API는 드라이버 중립적입니다. 두 kind 모두 동일한 소스 정보와 동일한 변경 이벤트를 반환하며, 게시하는 기능에서만 차이가 납니다.

로딩

local cdc = require("cdc")

list_sources

호출자가 볼 수 있는 구성된 CDC 소스를 나열합니다:

local sources, err = cdc.list_sources()
for _, s in ipairs(sources) do
    print(s.id, s.kind, s.state, s.capabilities.before_images)
end

호출자가 cdc.source 권한을 갖지 못한 소스는 오류로 보고되지 않고 목록에서 생략됩니다.

반환: table, error

source

이름(항목 ID)으로 소스 하나를 가져옵니다:

local info, err = cdc.source("app:pg_cdc")
if info == nil then
    -- 해당 소스 없음
end

반환: table, error (소스 정보, 찾지 못하면 nil)

stream

소스에 변경 스트림을 엽니다. 채널이 변경 이벤트를 전달하는 cdc.Stream을 반환합니다:

local stream, err = cdc.stream("app:pg_cdc", {
    tables = { "public.users", "public.orders" },
    ops    = { "insert", "update" },
    buffer = 128,
})
매개변수 타입 기본값 설명
name string 필수 소스 이름 (항목 ID)
opts.tables []string - 이 테이블들로 필터링 (모든 캡처 테이블을 원하면 생략)
opts.ops []string - 이 작업들로 필터링: insert, update, delete, truncate
opts.buffer int 64 백로그 항목 용량 (1-65536)
opts.max_bytes int 1048576 이 구독자의 백로그 바이트 예산 (1 MiB)
opts.snapshot bool 항목 기본값 이 스트림에 대해 스냅샷/라이브 인계를 요청
opts.after string - 이전 이벤트의 cursor에서 얻은 불투명 재개 커서

알 수 없는 옵션 키는 errors.INVALID로 거부됩니다. 테이블 이름은 정규화된 릴레이션과 순수 테이블 이름 양쪽에 대해 대소문자를 구분하지 않고 매칭됩니다. 스냅샷 행은 tables로만 필터링되며, ops는 라이브 변경에 적용됩니다.

opts.snapshot이 true이거나 소스 항목의 snapshot 필드가 설정된 경우 스트림은 스냅샷을 받습니다. 스냅샷 행이 op = "snapshot"으로 먼저 도착한 다음, 스트림은 빈틈 없이 라이브 변경으로 이어집니다. opts.after는 커서에서 재개하는 드라이버를 위해 예약되어 있습니다. 현재 제공되는 모든 드라이버는 이에 대해 errors.INVALID("cdc operation is not supported by this source")를 반환하며, capture_resume을 보고하는 db.cdc.postgres도 마찬가지입니다.

필터는 전달 범위를 좁힐 뿐입니다. 소스에 대한 접근은 cdc.subscribe 권한이 부여하는 것이지, 필터가 부여하지 않습니다.

반환: Stream, error

Stream 메서드

channel

변경 이벤트를 수신하는 채널을 반환합니다. 첫 호출이 소스를 구독하며(양보합니다), 이후 호출은 동일한 채널을 반환합니다. :receive()는 다음 변경이 도착할 때까지 블로킹하거나, 스트림이 끝나면 nil을 반환합니다:

local stream = cdc.stream("app:pg_cdc")
local ch = stream:channel()

while true do
    local change = ch:receive()
    if change == nil then break end   -- 스트림 닫힘

    if change.op == "snapshot" then
        seed_row(change.table, change.after)
    elseif change.op == "insert" then
        handle_new_user(change.table, change.after)
    elseif change.op == "update" then
        handle_update(change.table, change.before, change.after)
    elseif change.op == "delete" then
        handle_delete(change.table, change.before)
    end
end

스트림은 지연 방식입니다. 먼저 생성한 다음, 관찰해야 할 쓰기를 발생시키기 전에 channel()을 호출하십시오. 이는 라이브 관찰이며, 구독 이전에 발생한 변경의 재생이 아닙니다.

소스가 실패로 스트림을 종료하면, 채널은 닫히기 전에 오류 값을 전달합니다. receive는 channel의 별칭입니다.

close

구독을 중단하고 스트림을 해제합니다. 멱등하며, 태스크 스코프에서 자동으로도 닫힙니다. release는 close의 별칭입니다.

stream:close()

변경 이벤트

채널에서 수신하는 각 메시지는 변경 테이블입니다:

필드 설명
op 작업: insert, update, delete, snapshot 또는 truncate
schema 테이블 스키마
table 테이블 이름
relation 정규화된 릴레이션 이름
before 변경 이전 행 상태 (update, delete). 전체 행 이미지는 소스가 before_images 기능을 가질 때만 보장됩니다. db.cdc.postgres는 WAL이 실어 나르는 이전 튜플로 이를 채우며, 그 내용은 테이블의 REPLICA IDENTITY가 제어합니다
after 변경 이후 행 상태 (insert, update, snapshot, delete에는 없음)
source 소스 항목 ID
source_id 레지스트리 ID 형태의 소스 항목 ID
generation 이벤트를 생성한 소스 세대
cursor 소스 내 이벤트별 불투명 위치
transaction 드라이버가 보고하는 경우의 트랜잭션 식별자
lsn 변경의 로그 시퀀스 번호 (db.cdc.postgres)
commit_lsn 커밋 트랜잭션의 LSN (해당하는 경우)
xid 트랜잭션 ID (해당하는 경우)
unchanged 값이 전송되지 않은 컬럼 (변경되지 않은 TOAST 값)
error 이벤트에 실린 드라이버 보고 오류 설명

before와 after는 컬럼 이름을 키로 하는 행 맵입니다.

소스 정보

cdc.source와 cdc.list_sources의 각 항목은 동일한 레코드를 반환합니다:

필드 설명
id 항목 ID
kind db.cdc.postgres 또는 db.cdc.sqlite
name 소스 이름 (항목 ID)
state unknown, starting, running, faulted 또는 stopped
generation 현재 소스 세대
epoch generation과 동일한 값
engine 드라이버가 보고하는 경우의 엔진 이름
db_resource 관찰 대상 SQL 리소스 항목 ID (db.cdc.sqlite)
slot 복제 슬롯 이름 (db.cdc.postgres)
publication 구성된 경우 Postgres publication
tables 구성된 경우 캡처 대상 테이블
streaming db.cdc.sqlite: 소스가 실행 중인지 여부, db.cdc.postgres: 항목의 streaming 프로토콜 설정
failover 페일오버 슬롯 모드 (db.cdc.postgres)
temporary 임시 슬롯 (db.cdc.postgres)
snapshot 항목 수준 스냅샷 기본값
faulted 소스가 faulted 상태인지 여부
error 기록된 경우 마지막 소스 오류
admission active, snapshots, reserved_bytes, rejected
capabilities snapshot, capture_resume, replayable, captures_external_writes, before_images, coalesced

kind가 아니라 capabilities로 분기하십시오:

local info = cdc.source("app:changes")
if not info.capabilities.before_images then
    -- before가 전체 행 이미지로 보장되지 않으므로 마지막으로 알려진 상태를 직접 유지
end

필드 의미는 CDC 소스를 참조하십시오.

권한

작업 리소스 설명
cdc.source 소스 항목 ID cdc.source, cdc.list_sources도 필터링
cdc.subscribe 소스 항목 ID cdc.stream, 구독이 확립될 때 다시 확인

거부된 작업은 errors.PERMISSION_DENIED를 반환합니다.

오류

조건 종류
컨텍스트 없음 errors.INTERNAL
소스 이름이 필요함 errors.INVALID
유효하지 않거나 알 수 없는 스트림 옵션 errors.INVALID
capture_resume이 없는 소스에 after 사용 errors.INVALID
소스가 등록되지 않음 errors.NOT_FOUND
소스가 시작되지 않았거나 교체 중 errors.UNAVAILABLE
구독 용량 소진 errors.UNAVAILABLE
권한 거부 errors.PERMISSION_DENIED

오류를 다루는 방법은 오류 처리를 참조하십시오.

참고