CDC介绍
1 CDC
Change Data Capture:定义了一种场景,即识别并捕获数据库表中数据的变更,并交付给下游进一步处理。CDC是对针对行级数据记录的。其中数据的变更信息,即 CDC 的数据结构,包括变更是什么样的操作(有三类:insert,update,delete),变更发生的时间点,以及变更前后的数据。显然对于insert操作该记录的变更信息中是没有旧值的,对于 delete 操作该记录的变更信息中是没有新值(当前值)的。
2. CDC 典型方法
CDC 不是数据湖格式特有的概念和场景,它存在已久。并且在传统数据库有些一些典型的方法:
- 时间戳/版本号:是在表上添加一个类似于 created_time 和 last_modified_time 这样的字段,标识记录的创建时间和最新修改时间,查询时根据 modified_time 做过滤,得到变化的数据。这个方法有几个明显的缺点:
a. 不能感知到delete的变化。
b. 不能直接获取得到update的旧值,因此这类方案仅适用于没有delete操作,且不关注旧值的业务场景。
c. 由于没有快照或者版本的概念,不能准确的捕捉每次变更。 - 表Diff:通过对比表的前后两个状态或者快照的数据来获取 CDC 数据。由于要做Diff,就会有快照间 Join 操作,该方法查询性能较差,且占用更多的计算资源。
- 数据库的触发器:有些数据库如 Oracel 等支持为 insert,update,delete 操作创建触发器。在执行 insert/update/delete 操作时,自动将旧值和新值,以及操作类型,和时间戳等信息写入另外一张影子表。由于直接将变更的数据写入到了另外一张表,可以直接使用 sql 查询得到,查询性能和语法支持都较好。但这个方法增加了写入时开销。
- 事务日志:目前数据库会保留了表的操作事务日志,用于备份和系统恢复。我们可以从这里面提取出 CDC 数据,像 MySQL,RDS 等这类数据库都支持。该方法不会增加写入的开销,但获取 CDC 数据需要从事务日志解析出来,同时由于事务日志会定期归档,不会永久保存,需要及时读取出来,这也就是我们通常会对接 Kafka 来消费 binlog 的场景。
3. CDC输出格式
关于 CDC 的输出格式,我认为只要包含了全局的变更信息,包括操作类型,操作时间或对应版本,以及前后值就足够。这里列出了典型的 debezium 的格式,和上面场景示例中使用的格式,也是 deltalake 所采用的。debezium 是一个较为通用的格式,便于集成到已有系统中,而在部分场景 deltalake 自定义的格式对SQL查询更友好
4. CDC具备的能力
- 变更信息中应该包含所有的表字段,不能仅包括主键的;
- 对于 delete/update 操作,应该包括操作前的旧值;
- 能追溯每一次的变更。