FLink-CDC 的Oracle连接器的demo

利用flink的DatStream API 创建任务

 public static void main(String[] args) throws Exception {
        SourceFunction<String> sourceFunction = OracleSource.<String>builder()
                .url("jdbc:oracle:thin:@hadoop103:1521:ORCL")  // 用来连接oracle的url
                .port(1521)	// oracle  的端口号
                .database("ORCL") // 监听的数据库
                .schemaList("SCOTT") // 监听的schema
                .tableList("SCOTT.USERS ,SCOTT.APPS") // 监听的表
                .username("system") // 用户名
                .password("Oracle123") // 密码 
                //	.deserializer(new JsonDebeziumDeserializationSchema()) // 将结果以json格式进行输出。
				.deserializer(new OracleDeserializationSchema ()) 		// 自定义的输出格式
                .build();

        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

        env.addSource(sourceFunction)
           .print().setParallelism(1); // use parallelism 1 for sink to keep message ordering

        env.execute();
    }

自定义输出格式 - -> {schema:xx , table:xx, data:{xx:xx,yy:yy}}

import com.alibaba.fastjson.JSONObject;
import com.ververica.cdc.debezium.DebeziumDeserializationSchema;
import org.apache.flink.api.common.typeinfo.BasicTypeInfo;
import org.apache.flink.api.common.typeinfo.TypeInformation;
import org.apache.flink.util.Collector;
import org.apache.kafka.connect.data.Field;
import org.apache.kafka.connect.data.Schema;
import org.apache.kafka.connect.data.Struct;
import org.apache.kafka.connect.source.SourceRecord;

import java.math.BigDecimal;
import java.util.LinkedHashMap;
import java.util.List;

public class OracleDeserializationSchema implements DebeziumDeserializationSchema<String> {


    @Override
    public void deserialize(SourceRecord record, Collector<String> out) throws Exception {
        JSONObject result = new JSONObject(new LinkedHashMap<>());
        /*得到schema 和  table*/
        String topic = record.topic();
        String[] fields = topic.split("\\.");
        result.put("schema", fields[1]);
        result.put("table", fields[2]);
        /*得到after数据*/
        Struct value = (Struct) record.value();
        Struct after = (Struct) value.get("after");
        JSONObject afterJson = new JSONObject(new LinkedHashMap<>());
        if (after != null) {
            Schema schema = after.schema();
            List<Field> fieldList = schema.fields();
            for (Field field : fieldList) {
					/*
					 	由于通过归档日志读取到的number类型的数据格式为:{scale=2,value=[B@6e0782b5}
						scale :数值的精度,及小数点后几位;value:数值的二进制数组的格式
					 	需要将改格式转化成实际数据库中存储的格式
						主要思路是,将value的值转化为 long类型,将scale的值转化为int类型,通过BigDecimal.valueOf()方法得到存储的值
					 */
                if (after.get(field) instanceof Struct) {
                    Struct fieldValue = (Struct) after.get(field);
                    byte[] bytes = fieldValue.getBytes("value");
                    String l = Byte.toString(bytes[0]);
                    afterJson.put(field.name(), l);
                    Integer scale = fieldValue.getInt32("scale");
                    BigDecimal valueOf = BigDecimal.valueOf(Long.valueOf(l), scale);
                    afterJson.put(field.name(), valueOf.toString());
                } else {
                    afterJson.put(field.name(), after.get(field));
                }
            }
        }
        result.put("data", afterJson);
        out.collect(result.toJSONString());
    }

    @Override
    public TypeInformation<String> getProducedType() {
        return  BasicTypeInfo.STRING_TYPE_INFO;
    }
}

问题及解决

1、归档日志满了怎么办 ,也就是报错:ORA-00257: archiver error. Connect internal only, until freed 

rman target sys/pass
crosscheck archivelog all;
delete expired archivelog all;

2、Oracle CDC 的归档日志增长很快,且读取 log 慢?

可以使用在线挖掘的模式,不写入数据字典到 redo log 中,但是这样无法处理 DDL 语句。 生产环境默认策略读取 log 较慢,且默认策略会写入数据字典信息到 redo log 中导致日志量增加较多,可以添加如下 debezium 的配置项。 'log.mining.strategy' = 'online_catalog', 'log.mining.continuous.mine' = 'true'。如果使用 SQL 的方式,则需要在配置项中加上前缀 'debezium.',即:

请不要在连接到 Oracle 12c 或更高版本时使用该参数

Properties debeziumProperties = new Properties();
debeziumProperties.setProperty("log.mining.strategy", "online_catalog");
debeziumProperties.setProperty("log.mining.continuous.mine", "true"); 
builder.debeziumProperties(debeziumProperties);	

3、作业报错 Caused by: io.debezium.DebeziumException: Supplemental logging not configured for table xxx. Use command: ALTER TABLE xxx ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS, 怎么办呢?

对于 oracle11 版本,debezium 会默认把 tableIdCaseInsensitive 设置为true, 导致表名被更新为小写,因此在oracle中查询不到 这个表补全日志设置,导致误报这个Supplemental logging not configured for table 错误”。 添加 debezium 的配置项 'database.tablename.case.insensitive' = 'false', 如果使用 SQL 的方式,则在表的 option 中添加配置项 'debezium.database.tablename.case.insensitive' = 'false'

4、 Oracle CDC 如何切换成 XStream 的方式?

添加 debezium 的配置项 'database.connection.adpter' = 'xstream', 如果使用 SQL 的方式,则在表的 option 中添加配置项 'debezium.database.connection.adpter' = 'xstream'

5、 Oracle CDC 的 database-name 和 schema-name 分别是什么

database-name 是数据库示例的名字,也就是 Oracle 的 SID schema-name 是表对应的 schema,一般而言,一个用户就对应一个 schema, 该用户的 schema 名等于用户名,并作为该用户缺省 schema。所以 schema-name 一般都是创建这个表的用户名,但是如果创建表的时候指定了 schema,则指定的 schema 则为 schema-name。 比如用 CREATE TABLE aaaa.testtable(xxxx) 的方式成功创建了表 testtable, 则 aaaa 为 schema-name。

参考:

Oracle CDC Connector — CDC Connectors for Apache Flink® documentation (ververica.github.io)

FAQ(ZH) · ververica/flink-cdc-connectors Wiki · GitHub

6、Oracle CDC 读取不到大文件,即:BLOB 和 CLOB 类型的数据

这是由于 debezium 的参数 lob.enabled 决定的,默认为 false ,可以修改为 lob.enabled=true

该参数的作用是:控制是否在更改事件中发出大型对象(CLOB 或 BLOB)列值。

默认情况下,变更事件具有较大的对象列,但这些列不包含任何值。 在处理和管理大型对象列类型和有效负载时存在一定的开销。 要捕获大型对象值并在更改事件中序列化这些值,请将此选项设置为 。true

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值