Paimon在数据同步的过程中支持动态捕获源数据库的Schema变更,并将变化实时更新到Paimon表中,同时会保留每次变更的Schema的json文件到HDFS中,本次主要学习与测试在不中断流式作业的前提下,Paimon对于Schema变更的支持性。
Paimon的版本:0.8、Flink的版本:1.18.1
- 新增字段,并且在源数据库新增字段中插入值
- 字段名修改
- 字段类型修改
- 删除字段
新增字段
- 测试cdc同步mysql场景,首先启动同步任务,同步mysql中的订单表到paimon中
[root@node001 flink-1.18.1]# bin/flink run \
> /opt/model/flink-1.18.1/opt/paimon-flink-action-0.8-20240709.052248-82.jar \
> mysql-sync-table \
> --warehouse hdfs://node001:8020/paimon/hive \
> --database default \
> --table order_detail_cdc \
> --primary-keys order_id \
> --mysql-conf hostname=node003 \
> --mysql-conf username=root \
> --mysql-conf password=123456 \
> --mysql-conf database-name=test \
> --mysql-conf table-name='order_detail' \
> --catalog-conf metastore=hive \
> --catalog-conf uri=thrift://node001:9083 \
> --table-conf bucket=4 \
> --table-conf changelog-producer=input \
> --table-conf sink.parallelism=4
- 在sql-client中查询paimon表,可以看到历史数据已经成功被同步过来
- 在mysql中修改订单表,新增一列user_name
alter table order_detail add column user_name varchar(255);
- 由于这里我的流式查询已经启动,为了看到paimon的schema是否同步更新了,可以直接去hdfs上看对应的paimon表的schema文件,可以直接使用hdfs命令查看,也可以去nameNode的UI上去看。
mysql依赖问题
hdfs dfs -ls /user/hive/warehouse/order_detail_cdc/schema | wc -l
hdfs dfs -cat /user/hive/warehouse/order_detail_cdc/schema/schema-0 | grep user_name
?发现schema只有一条,也就是没有生成新的schma文件,查看该文件发现字段元数据还是之前的,没有更新新增的字段,但是Paimon应该是支持这个功能的。
查看Flink集群对应任务的TaskManager日志,发现缺失报错了,判断应该是字段的类型转换相关的兼容性问题。
查看我的flink的lib目录,我的mysql-connector原来的版本是8.0.20的,flink的cdc-mysql的版本为3.2.0,是个很新的版本,网上搜索说是因为flink包里面的依赖和mysql自身的依赖冲突了,需要替换mysql-connector的版本为8.0.21或以上。
这里值得注意的一个点是,我替换jar包后,重启集群和cdc的任务,一开始提交失败了,说我paimon表和mysql表的字段映射对不上,这是因为我之前已经添加了user_name字段,paimon在提交的时候会检查字段的映射状况,默认情况下是不会忽略这种映射不上的事件,会直接抛异常。
- 重置所有组件到事前快照,从新提交,发现paimon表的schema文件成功更新了。
查看文件内容,paimon元数据被实时的更新了,新增了user_name字段。
- 观察我的实时查询任务,发现flink并没有为这种元数据的变更而新增一条数据记录,为了看到这种变化,我修改mysql中的一条订单记录,触发paimon表的数据更新。但是发现paimon新增的数据记录中,并没有将user_name字段查询出来,只是更新的原来几个字段的数据变化,个人理解应该是流式任务在提交时会扫描提交时paimon表最新的schema文件进行查询,虽然后续的schema会实时的更更新,但是不会对该任务的结果产生影响。
UPDATE order_detail SET sku_id = 5 WHERE order_id = 1;
- 尝试更新mysql的user_name的字段值,看看flink是否能刷出数据,可以看到确实新增记录了,但是user_name字段不会在查询结果中,因此想做到元数据+数据完全更新,必须重新提交flink任务。
UPDATE order_detail SET user_name = "zhu" WHERE order_id = 1;
修改字段
后续更新
删除字段
后续更新