oracle cdc 数据同步,13.Oracle CDC 同步数据 Kafka.md

# Oracle CDC 同步数据 Kafka

## 简介

本章节介绍如何使用Oracle自带的LogMiner来提取数据归档日志,并识别输出到Kafka集群,用于后期实时计算业务场景。

## 环境

OS: Windows 10

内存:32GB

部署:docker desktop

## 效果

### docker服务

![image-20200821145345466](image/ora2kafka-20200821145345466.png)

## StreamSets DataCollector

![image-20200821145548943](image/ora2kafka-20200821145548943.png)

#### 同步作业运行效果

![image-20200821145659612](image/ora2kafka-20200821145659612.png)

#### Oracle增删改操作更新Kafka

![image-20200821145927367](image/ora2kafka-20200821145927367.png)

## 一、Oracle11g 容器搭建

从docker hub上获取一个oracle11g的镜像,在本地docker中安装好oracle容器

```shell

docker run --name oracle11g -d -p 49162:1521 -e ORACLE_ALLOW_REMOTE=true oracleinanutshell/oracle-xe-11g

```

### 任务1:启用LogMiner

#### (1)作为具有DBA特权的用户登录数据库

#### (2)检查数据库日志记录模式:

```sql

select log_mode from v$database;

```

如果返回ARCHIVELOG,跳到任务2.

如果返回NOARCHIVELOG,继续以下步骤:

#### (3)关闭数据库:

```sql

shutdown immediate;

```

#### (4)启动、挂载数据库

```

startup mount;

```

#### (5)配置启用存档、打开数据库

```sql

alter database archivelog;

alter database open;

```

### 任务2:为数据库或表启用补充日志记录

​ 要从重做日志检索数据,LogMiner需要数据库或表的补充日志记录。

​ 对于要使用的每个表,在表级别上至少启用主键或“标识键”日志记录。使用标识键日志记录,记录只包括主键和更改的字段。

​ 由于Oracle已知的问题,要为表启用补充日志记录,必须首先为数据库启用最小补充日志记录。

​ 要在origin生成的记录中包含所有字段,请在表或数据库级别启用完整的补充日志记录。完整的补充日志记录提供了来自所有列的数据,包括未更改数据以及主键和已更改列的数据。

#### (1)要验证是否为数据库启用了补充日志记录,请运行以下命令:

```sql

SELECT supplemental_log_data_min, supplemental_log_data_pk, supplemental_log_data_all FROM v$database;

```

如果都返回YES,则跳到任务3;

#### (2)启用标识键或完整补充日志记录。

**启用标识键日志记录**

可以为数据库中的单个表或所有表启用标识键日志记录:

- 单个表

```sql

ALTER DATABASE ADD SUPPLEMENTAL LOG DATA;

ALTER TABLE .

```

- 所有表

```sql

ALTER DATABASE ADD SUPPLEMENTAL LOG DATA (PRIMARY KEY) COLUMNS;

```

**启用完整的补充日志记录**

可以为数据库中的单个表或所有表启用完整的补充日志记录.

- 单个表

```sql

ALTER DATABASE ADD SUPPLEMENTAL LOG DATA;

ALTER TABLE .

```

- 所有表

```sql

ALTER DATABASE ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;

```

#### (3)提交变更:

```sql

ALTER SYSTEM SWITCH LOGFILE;

```

### 任务3:创建用户账号

创建一个与OCC Origin一起使用的用户帐户。可以根据所使用的Oracle版本以不同的方式创建帐户。

#### **Oracle 12c multitenant databases**

1. 作为具有DBA特权的用户登录数据库。

2. 创建常用用户帐号:

```sql

ALTER SESSION SET CONTAINER=cdb$root;

CREATE USER IDENTIFIED BY CONTAINER=all;

GRANT create session, alter session, set container, select any dictionary, logmining, execute_catalog_role TO CONTAINER=all;

ALTER SESSION SET CONTAINER=;

GRANT select on .

```

#### **Oracle 12c standard databases**

1. 作为具有DBA特权的用户登录数据库。

2. 创建常用用户帐号:

```sql

CREATE USER IDENTIFIED BY ;

GRANT create session, alter session, select any dictionary, logmining, execute_catalog_role TO ;

GRANT select on .

```

#### **Oracle 11g databases**

1. 作为具有DBA特权的用户登录数据库。

2. 创建实时数据同步用户帐号: rtsync

```sql

CREATE USER rtsync IDENTIFIED BY rtsync0820#;

GRANT create session, alter session, execute_catalog_role, select any dictionary, select any transaction, select any table to rtsync;

GRANT select on v_$logmnr_parameters to rtsync;

GRANT select on v_$logmnr_logs to rtsync;

GRANT select on v_$archived_log to rtsync;

GRANT select on gv_$logmnr_parameters to rtsync;

GRANT select on gv_$logmnr_logs to rtsync;

GRANT select on gv_$archived_log to rtsync;

```

3. 将需要实时同步日志的表的select权限赋权给rtsync用户:

```sql

GRANT select on HR.JOBS TO rtsync;

```

### 任务4:抽取LogMIner的catalog日志

oracle的catalog日志只能获取对表的DML操作日志,如果要连oracle的DDL日志也获取到,则需要配置redolog

#### 使用oracle的预设存储过程,在当前SCN中启动LogMiner

1. 数据库主机oracle用户登录,先确保/tmp目录中没有add_logfiles.sql文件

2. 作为具有DBA特权的用户登录数据库。

```sql

--- 添加已经存在的logfiles,并且设置DBMS_LOGMNR持续的从archivelogs中获取归档日志

SQL> set linesize 200 trimspool on pagesize 0

--- 添加已经存在的logfiles,忽略备份(STANDBY)的logfiles

SQL> select 'exec dbms_logmnr.add_logfile('''||member||''')'

from v$logfile

where type <> 'STANDBY'

and member in (select min(member) from v$logfile group by group#)

/

```

查询生成语句输出如下:

```shell

exec dbms_logmnr.add_logfile('/u01/app/oracle/fast_recovery_area/XE/onlinelog/o1_mf_2_g6c5nj25_.log')

exec dbms_logmnr.add_logfile('/u01/app/oracle/fast_recovery_area/XE/onlinelog/o1_mf_1_g6c5nhsl_.log')

```

3. 将上面的输出spool写入到/tmp/add_logfiles.sql文件中

```SQL

--- 将上面的输出spool写入到/tmp/add_logfiles.sql文件中

SQL> spool /tmp/add_logfiles.sql

SQL> /

SQL> spool off

```

4. 执行如下语句,开始启动logminer

```sql

SQL> exec dbms_logmnr.start_logmnr(options => DBMS_LOGMNR.DICT_FROM_ONLINE_CATALOG + DBMS_LOGMNR.CONTINUOUS_MINE + DBMS_LOGMNR.COMMITTED_DATA_ONLY)

```

5. 查询日志是否已经启动logMiner

```sql

select log_mode from v$database;

```

如果输出为ARCHIVELOG,则说明当前已经打开了logminer的catalog日志监听

### 任务5:抽取Log Miner Dictionary(Redo Logs)

​ 当需要获取oracle的DDL日志,即表结构的各种变化,则需要使用redo logs作为字典源,必须在启动pipeline之前将Log Miner字典提取到redo logs。而且需要定期重复此步骤,以确保包含字典的redo logs仍然可用。

​ Oracle建议只在非高峰时间提取字典,因为提取会消耗数据库资源。

​ 要提取Oracle 11g或12c数据库的字典,请运行以下命令:

```sql

EXECUTE DBMS_LOGMNR_D.BUILD(OPTIONS=> DBMS_LOGMNR_D.STORE_IN_REDO_LOGS);

```

​ 要提取Oracle 12c多租户(CDB+多个PDB)数据库的字典,请运行以下命令:

```sql

ALTER SESSION SET CONTAINER=cdb$root;

EXECUTE DBMS_LOGMNR_D.BUILD(OPTIONS=> DBMS_LOGMNR_D.STORE_IN_REDO_LOGS);

```

## 二、安装StreamSets的DataCollector工具

如果你当前使用的是CDH环境,那么可以直接部署安装对应版本的DataCollector工具,如果你和我一样是一个测试玩家,那么可以和我一起继续玩下去

1. 命令行获取`streamsets/datacollector:3.14.0`的镜像

```shell

docker pull streamsets/datacollector:3.14.0

```

2. 创建容器之前,先需要初始化几个volume,为了组件扩展方便一点,我选择了这种部署方式

```shell

# 用于挂在配置文件

docker volume create sdc-conf

# 用于存放pipeline的元数据

docker volume create sdc-data

# 用于存放streamsets官方提供的组件库

docker volume create sdc-stagelibs

# 用于存放临时资源

docker volume create sdc-resources

# 用于存放用户自定义开发的组件

docker volume create sdc-user-libs

# 用于存放组件需要用到的扩展jar包,例如各种数据库的JDBC驱动

docker volume create sdc-streamsets-libs-extras

```

3. 获取完毕之后,启动一个对应的容器:增加一个-verbose参数是为了输出多一点日志信息

```shell

docker run --name sdc -d \

-v sdc-conf:/etc/sdc \

-v sdc-data:/data \

-v sdc-stagelibs:/opt/streamsets-datacollector-3.14.0/streamsets-libs \

-v sdc-resources:/resources \

-v sdc-user-libs:/opt/streamsets-datacollector-3.14.0/user-libs \

-v sdc-streamsets-libs-extras:/opt/streamsets-datacollector-3.14.0/streamsets-libs-extras \

-p 18630:18630 --network host streamsets/datacollector:3.14.0 dc -verbose

```

4. 此时你可以从本地登录datacollector的操作界面了,默认密码admin

![image-20200821151941970](image/ora2kafka-20200821151941970.png)

## 三、SDC安装JDBC和KAFKA组件

### 创建一个docker容器,部署操作volume

由于部署主机为Windows10环境,所以我们没有办法直接在本地访问docker创建出来的volume,所以我们先需要安装一个host docker container用户访问windows的volume,从而给SDC扩展功能。

```shell

docker run --net=host --ipc=host --uts=host --pid=host -it --security-opt=seccomp=unconfined --privileged --rm -v /:/host centos /bin/bash

```

切换主机环境:

```shell

chroot /host

```

如此该环境和windows的环境基本融合了

```

ls

```

![image-20200821152738840](image/ora2kafka-20200821152738840.png)

C就是我们windows的C盘,D就是D盘

```shell

docker volume ls

```

![image-20200821152916120](image/ora2kafka-20200821152916120.png)

```shell

docker inspect sdc-stagelibs

```

![image-20200821153238220](image/ora2kafka-20200821153238220.png)

如此我们就可以复制本地的扩展组件到对应的volume卷中了,如上图,我在sdc-stagelibs卷中创建了jdbc-lib和kafka_2_0-lib目录,用于安装组件

```shell

cd /var/lib/docker/volumes/sdc-stagelibs/_data

mkdir streamsets-datacollector-jdbc-lib/lib -p

mkdir streamsets-datacollector-apache-kafka_2_0-lib/lib -p

```

复制组件jar包到这两个目录中,组件jar包可以按照本套教程的第8章节《WSL编译》进行编译获得

```shell

cd /var/lib/docker/volumes/sdc-stagelibs/_data/streamsets-datacollector-jdbc-lib/lib

cp /host_mnt/d/iProject/streamsets/datacollector-3.14.0/dist/target/streamsets-datacollector-3.14.0/streamsets-datacollector-3.14.0/streamsets-libs/streamsets-datacollector-jdbc-lib/lib/* ./

cd /var/lib/docker/volumes/sdc-stagelibs/_data/streamsets-datacollector-apache-kafka_2_0-lib/lib

cp /host_mnt/d/iProject/streamsets/datacollector-3.14.0/dist/target/streamsets-datacollector-3.14.0/streamsets-datacollector-3.14.0/streamsets-libs/streamsets-datacollector-apache-kafka_2_0-lib/lib/* ./

```

部署完毕之后,我们重新启动这个sdc容器服务。

## 四、启动KAFKA、JDBC组件,上传JDBC驱动

因为是手动安装,所以还需要手动注册组件,点击右上方Package Manager按钮,分别注册Kafka和JDBC组件,如下:

### 点亮Kafka组件

![image-20200821154627723](image/ora2kafka-20200821154627723.png)

### 点亮JDBC组件

![image-20200821154841274](image/ora2kafka-20200821154841274.png)

### 创建一个测试用的pipline,就可以看到对应组件的图标了

![image-20200821155038311](image/ora2kafka-20200821155038311.png)

### 继续上传JDBC组件

![image-20200821155238344](image/ora2kafka-20200821155238344.png)

![image-20200821155312905](image/ora2kafka-20200821155312905.png)

可以把常用的JDBC驱动全部传上去。传完之后,可以浏览一下`sdc-streamsets-libs-extras`这个卷下面,就是我们传上去的jar包。

![image-20200821155517174](image/ora2kafka-20200821155517174.png)

## 五、创建一个pipeline,用于从Oracle的日志中获取发生变化的数据事件,写入数据到kafka

### 配置Oracle CDC Client组件,用于获取Oracle logminer日志

![image-20200821160138301](image/ora2kafka-20200821160138301.png)

配置一张表HR.JOBS,获取INSERT、UPDATE、DELETE、SELECT_FOR_UPDATE的操作事件,字典源选择为Online Catalog

![image-20200821160244057](image/ora2kafka-20200821160244057.png)

配置JDBC链接串

![image-20200821160312867](image/ora2kafka-20200821160312867.png)

配置用户密码

![image-20200821160407454](image/ora2kafka-20200821160407454.png)

### 配置一个kafka producer组件,用于向kafka写入数据

在对应的kafka集群创建一个topic: orasync

![image-20200821160924318](image/ora2kafka-20200821160924318.png)

数据写入kafka的格式使用JSON

![image-20200821161058721](image/ora2kafka-20200821161058721.png)

### 配置一个JS组件,加入操作信息

默认的写入kafka的内容只有数据体,但是我们还想要区分一下到底是INSERT/DELETE/UPDATE的哪一种,所以我们在中间添加了一个JS的Processors组件

![image-20200821161236406](image/ora2kafka-20200821161236406.png)

添加我们编写的脚本

![image-20200821161539127](image/ora2kafka-20200821161539127.png)

脚本内容:

```javascript

// Sample JavaScript code

var records = sdc.records;

for(var i = 0; i < records.length; i++) {

try {

// 克隆创建一个Record,这个是Streamsets DataCollector的内部数据传输结构

var newRecord = sdc.createRecord(records[i].sourceId);

// 创建一个map

var newMap = sdc.createMap(true);

// 按照官网的提示,直接获取header信息,可以records[i].oracle.cdc.operation,但是我并为测试成功,暂时写了一个循环,将表名和操作类型取出来

var headersMap = records[i].attributes

for(headKey in headersMap){

var headValue = headersMap[headKey];

if (headKey=='oracle.cdc.operation') {

newMap['opt']=headValue;

} else if (headKey=='oracle.cdc.table') {

newMap['table']=headValue;

}

}

// 添加原有数据到newMap

for(key in records[i].value){

var value = records[i].value[key];

newMap[key] = value;

}

// 赋值引用

newRecord.value = newMap;

// Write record to processor output

sdc.output.write(newRecord);

} catch (e) {

// Send record to error

sdc.error.write(records[i], e);

}

}

```

## 总结

最后将我们创建好的pipeline运行起来,对目标表进行增删改操作,去对应的kafka里面查看写入情况,就达到了我们开头介绍的效果。

一键复制

编辑

Web IDE

原始数据

按行查看

历史

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Oracle CDC(Change Data Capture)是一种用于捕获数据库变更的技术,它可以将数据库中的变更事件捕获并转换成易于消费的数据流。通过CDC,可以将数据库中的变更事件用于实时数据分析、数据集成、数据同步等场景。 异步在线日志CDC是一种基于Oracle数据库在线日志的CDC方式,它可以实现高性能的数据捕获和传递。异步在线日志CDC的部署可以分为以下步骤: 1. 创建CDC用户和日志表 在Oracle数据库中,需要创建一个CDC用户和一个日志表,用于存储捕获到的变更事件。可以使用以下SQL语句创建CDC用户和日志表: ``` CREATE USER cdc_user IDENTIFIED BY password; GRANT CONNECT, RESOURCE, DBA TO cdc_user; CREATE TABLE cdc_log ( scn NUMBER(38), timestamp TIMESTAMP(6), table_name VARCHAR2(30), operation_type VARCHAR2(1), primary_keys VARCHAR2(4000), columns_changed VARCHAR2(4000) ); ``` 2. 创建CDC组件 需要在Oracle数据库中创建CDC组件,用于启用CDC功能。可以使用以下SQL语句创建CDC组件: ``` BEGIN DBMS_CDC_PUBLISH.CREATE_CHANGE_TABLE ( change_table_name => 'cdc_change_table', source_schema_name => 'source_schema', source_table_name => 'source_table', column_type_list => 'column1 NUMBER, column2 VARCHAR2(50)', capture_values => 'both', rs_id => TRUE, row_id => TRUE, user_id => TRUE, timestamp => TRUE ); DBMS_CDC_SUBSCRIBE.CREATE_SUBSCRIPTION ( subscription_name => 'cdc_subscription', source_schema => 'source_schema', source_table => 'source_table', column_list => 'column1, column2', subscriber => 'cdc_user', subscription_type => 'asynchronous', sync_on_commit => FALSE ); END; ``` 3. 配置CDC捕获过程 需要在Oracle数据库中配置CDC捕获过程,用于将变更事件写入到日志表中。可以使用以下SQL语句配置CDC捕获过程: ``` BEGIN DBMS_CDC_PUBLISH.ALTER_CHANGE_TABLE ( change_table_name => 'cdc_change_table', capture_values => 'both', rs_id => TRUE, row_id => TRUE, user_id => TRUE, timestamp => TRUE ); DBMS_CDC_SUBSCRIBE.ALTER_SUBSCRIPTION ( subscription_name => 'cdc_subscription', column_list => 'column1, column2' ); DBMS_CAPTURE_ASYNCH_CAPTURE.SET_PARAMETER ( parameter_name => 'ASYNC_COMMIT_TIMEOUT', parameter_value => '30' ); DBMS_CAPTURE_ASYNCH_CAPTURE.SET_PARAMETER ( parameter_name => 'ASYNC_COMMIT_BATCH_SIZE', parameter_value => '1000' ); DBMS_CAPTURE_ASYNCH_CAPTURE.START_CAPTURE ( capture_name => 'cdc_capture', capture_user => 'cdc_user', capture_process => 'ASYNC_CAPTURE', capture_window_size => '3600', queue_name => 'cdc_queue', capture_enqueue_time => 'true', enqueue_name => 'cdc_enqueue', include_tagged_lcr => 'all' ); END; ``` 4. 消费CDC日志 最后,需要编写消费CDC日志的程序,将捕获到的变更事件用于实时数据分析、数据集成、数据同步等场景。可以使用Oracle GoldenGate、Kafka等工具来消费CDC日志。 需要注意的是,在使用异步在线日志CDC时,需要确保捕获过程和消费程序的性能足够高,以避免数据延迟和丢失等情况的发生。同时,还需要进行详细的测试和监控,以确保CDC系统的稳定性和可靠性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值