首页/数据/数据工程与 ETL 速查/Debezium 事件结构与 op 字段
CDC 与同步53 条

Debezium 事件结构与 op 字段

Debezium 事件用 op 区分变更类型:c=INSERT、u=UPDATE、d=DELETE、r=快照读取。事件包含 before/after 行镜像、source 元数据(库表、binlog 文件与位点、GTID)与 ts_ms 时间戳;消费侧通常按 op 决定 upsert 或 delete,Kafka key 默认是表主键。

事件结构与 op 字段

Debezium 把每次变更输出成一条结构化事件:before 是变更前的行镜像,after 是变更后的行镜像,source 描述来源库表与日志位点,op 标明变更类型,ts_ms 是事件生成时间。消费侧按 op 决定如何写入目标,Kafka 消息键默认是表主键,因此同一主键的变更落在同一分区。

为什么必须按 op 分支处理

只读 after 字段是最常见的错误:删除事件的 after 为空,直接读取会写入空数据或直接报错;而快照事件(op=r)虽然形态像插入,但它表示存量数据的初始读取,把它当成新增事件做累加统计会让指标整体被放大。

op 取值读法

op含义before / after
cinsert(create)before 为 null,after 为新行
uupdatebefore 与 after 通常都有值
ddeletebefore 为旧行,after 为 null
r快照读取(snapshot read)before 为 null,after 为存量行
t仅事务边界消息(视配置产生)不含行数据,可忽略或用于审计

基本信息

事件字段before、after、source、op、ts_ms
消息键默认是源表主键,保证同键变更同分区
source 内容库表名、binlog 文件名与位点或 GTID
快照事件op=r,表示初始存量读取,不是新增数据
下游约定c/r 走 upsert,d 走 delete,u 走 upsert

典型使用场景

  • 数仓 ODS 落地:按 op 决定插入、更新还是删除目标行
  • 缓存维护:收到 c 或 u 刷新缓存,收到 d 删除缓存键
  • 审计留痕:保留 before 与 after 以记录变更前后内容
  • 对账核对:用 source 里的日志位点定位事件对应的源库位置
  • 指标统计:过滤掉 op=r 的存量事件,避免指标被初始数据放大

事件示例(op=c 插入)

事件示例(op=c 插入)
{
  "before": null,
  "after": { "order_id": 1001, "status": "PAID", "amount": "9.90" },
  "source": { "db": "app", "table": "orders",
               "file": "mysql-bin.000123", "pos": 4567 },
  "op": "c",
  "ts_ms": 1728612345678
}

下游按 op 分支处理

下游按 op 分支处理
-- 伪 SQL:展示分支逻辑,具体语法按所用引擎调整
-- c / u / r:按主键 upsert,重复投递结果一致
INSERT INTO dwd_order (order_id, status, amount)
SELECT after.order_id, after.status, after.amount FROM cdc_stream
WHERE op IN ('c', 'u', 'r');

-- d:按主键删除
DELETE FROM dwd_order
WHERE order_id IN (SELECT before.order_id FROM cdc_stream WHERE op = 'd');

-- 统计类需求:显式排除快照事件,避免存量数据被当成新增
SELECT COUNT(*) FROM cdc_stream WHERE op = 'c';
source 里的文件与位点(或 GTID)是事后回溯的关键线索:出现数据疑问时,可以据此定位到源库的哪一段时间、哪个位置,再结合原始日志核查。
把快照事件(op=r)当作新增数据做累计统计,指标会整体被放大到存量规模;初始化阶段通常需要把 op=r 与 op=c 分开统计,或在统计前先完成存量对齐。

易错点

  • 只读 after 字段写目标端,删除事件被写成空数据或直接报错
  • 把快照事件 op=r 当成新增数据做累加,指标被放大到存量规模
  • 忽略 before 字段,删除时无法取出主键,只能靠消息键或另存主键映射
  • 下游不按 op 分支而统一按插入处理,源库的更新与删除在目标端完全丢失

数据来源与参考

  • Debezium 官方文档(Event structure:op codes 与 source 元数据)
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌