100-ODI

简介

ODI(Oracle Date Integrator)是Oracle Fusion MiddleWare的一个组件,它可以实现不同以及相同异构数据源之间的数据同步与集成。
ODI的架构中,主要有以下的对象:Repository 仓库、Studio 工作室、Agent 代理、Console 工作台
1、Repository分为2种类型:Master和Work。
Master库主要用于存储拓扑信息及对Work库的版本控制,用户权限控制等的管理。
Work库是定义的各种用于ETL转换的对象,是实际的Project库。里面可以存储各种结构与对象。比如Project,Model,Interface,Workflow等等信息。可以基于Work库的这个特点,可以新建不同的Work,分别用于DEV,Exec等不同用途的库。达到以目的操作对应的库,方便设计权限等。尽可能独立存储,单独的Instance,或单独的Schema。
2、Agent
实际执行者的代理人角色。所要执行的SQL语句通过代理,首先连接到要执行的DB服务器,然后发送要执行的代码进行执行,并将结果发送到目标数据库。
Agent接受多种执行方式:Studio,Console,命令行,Web Service,ODI Schedules
环境说明:

  1. Win10(64位)
  2. ODI 11G
  3. JDK 1.8(64位)

安装

安装前设置setup.exe兼容性win7和管理员权限,安装过程中无特殊说明默认设置即可
c7aaea7160972b2278674c1373c04137
d98715fc2d6686bcf048fa0bb34c98ad
b7e8c5134853be43b6ab5d47810527b6
安装过程中会出现会要求选择第二个安装盘路径
ab9720b75bc585d3816a7401048c96fa

登陆配置

创建主资料档案库

先在ORACLE下拟先用orcl数据库用system用户,创建一个主资料档案库用户的数据库用户C##ODI_MASTER
创建完进入ODI,新建->主资料档案库创建向导
1af4c69c48290562a0b4098702430dd7
421d6d84a62e12b76bc3270334b36c53
b52ef1f025b53ef96fc71607891d71ee

创建主资料档案库-登录用户

上一步已经把ODI的系统配置导入到C##ODI_MASTER,现在开始创建基于此用户的ODI登陆用户
a70e7f43b76c379cc0a6e0976da28caf
a28b54699c33460b82d8838dcf26fa22
重复上一步,继续再创建一个开发工作使用的登陆用户
380efbce61068d615a30188587948692

创建开发工作资料档案库

在ORACLE下登陆system用户下创建工作资料档案库的用户C##ODI_WORK
登陆ODI主资料档案库用户后,选择拓扑->资料档案库->新建工作资料档案库
2c214b363b8d039ebd79088d4be68593
0fb21faea1be0b41ec88c283963314a0
46efc0a5afe01c997695f83d8a44ac0f
07c59c924d5c54ffb55874675d394874
创建完成后重新登录ODI ,选择开发工作资料档案库用户,点击编辑信息,将工作资料档案库选上即可,确认后登陆即可
9ef06d0fb3f56423890a14aee7a4d045
9629d03cf3898849397cf2a8e63f365d

数据库对接配置

创建数据库

简略写下创建源数据库SOURCE和目标数据库TARGET用于测试
da65accb8e57498c4e3574343968e569
04a7eccc1dbb024738d77671ab7272a2
730b3dc3bbaf3f7f099c485967126c67

创建数据服务器

拓扑->物理体系结构->Oracle 选中右键选择新建数据服务器
建立SOURCE的数据服务器,保存时提示警告先忽略不管
92ab6ed91c8f3bd8913978c9c27fb933
76288d61f6a335e4db5f53741a42617f
复上一步,再建立TARGET的数据服务器
a6f214d153a374eb08311cb55515a3c7
4afc6a808fd063fb8b423dbe098a8ab5
在刚建立的两个数据服务器上,分别右键新建两个物理方案
940b1892ec87ce2fe465a07b59e86113
23da8de4f7d38d5540cdc23a32ecce8c

创建逻辑方案

拓扑->逻辑体系结构->新建逻辑方案,选择刚建立的物理方案
952d0d59ad589a8c0ef120ce70fc969b
a0405df7ecce9f9b9af8e73e00abad1a

创建模型

模型用于将数据库表映射到ODI
213d30a0d8ce6335fd48dc015d18a58c
因为库中表较多,所以我们指定表进行逆向工程
81efa7d2e0cbcde71fd654b3feaefe9d
将SOURCE和TARGET的表分别通过逆向工程导入ODI
f8c65d78419a8e88e4c8cf2ed27dfdcc
我们需要建立三个相同表结构的表:SOURCE数据库:SOURCE_EMP,TARGET数据库:TARGET_EMP、TMP_TARGET_EMP
因为没给TMP_TARGET_EMP表建立主键,我们所以需要在ODI设置关键字,不然会报错:如果未在目标数据存储中声明关键字, 则不能进行流控制
de2227306fe37464def783b262686a2d
b871bed3bbeed95d34198626a0a86b0c

新建项目

ebe948c53379f6ba2ea5717e82ecd25b

导入知识模块

定义:知识模块(KM)是代码模板,定义什么类型的SQL查询(插入,选择,等等)或是哪些脚本需要生成来完成数据提取,加载和转换操作。
类型说明:

  • RKM:RKM完成从源系统和目标系统的数据结构的反向工程来形成数据模型的功能。
  • CKM:CKM完成数据质量检查。
  • LKM:LKM完成从源数据库数据加载到临时表。
  • IKM:IKM完成从临时表的数据加载到目标表。
  • SKM:SKM完成ODI和WEB服务接口的功能。
  • SKM(Service KM):Web服务知识模块,可以使用该知识模块来生成Web服务调用

53a459b4ad2687e83d09e70828f9a8b1

创建过程

因为在同一过程中处理SOURCE和TARGET不同数据源,所以这里勾选多连接,并选择数据库对应技术
2454913af7c2e47ca79d7f6e8485a336
建立过程中的处理,下面建的三个处理都是使用上一步三个表的建表脚本
4f9286eb74cc9c8f640ba63279d29d45
dc41a7d5bf336390c82d0004a13a1df6
可以先执行一遍,可以点击操作查看执行日志
f4de59368b1524b3ea1c876afa0c86f3
建立一个用于将TARGET的TMP表增量同步到正式表的过程
b83b44533de603b1bc5415e29001d59c
f4df808c7939affc174afa32e51f2b2a

创建接口

用于将SOURCE数据拉取到TARGET的TMP表
8823cc9335da757d0879b444a774a63d
6f04e1c587eeaf72896790c33446e0e7
我们建立的关键字在这里可以看到自动关联进来
1c84930e4d25d516cb2a80bebbaac502

新建程序包

2e828abfe97cac0b69ac89eeb82dd646
将过程和接口拖入图表区域连接起
e26aae3109ca937656fd155b66fb66eb
点击OdiSleep设置休眠时间
a60234c3a864c635bd23bc18890575a8
这样就完成了不同数据库数据的定时增量同步功能了~

调度

生成场景后,新建调度任务
f8ef33decb9e7eaeeb7b76254e92986f
设置重复间隔
dc697cc6bb46c321df712cfd3c4aec5d
查看设置的调度
16eab06df6b47c814969893d133854fd
设置调度后,并进入拓扑,打开对应的代理点击更新调度才能生效,点击查看调度可以查看到正在调度情况
9edc4684d437109727cbc20e77e5c4c4

FAQ

1、错误:ORA-00904: “LASTUPDATE”: 标识符无效
场景:接口同步报错,表中已经有LASTUPDATE字段,但是同步还是说标识符无效
原因:下图可以看到用ODI同步的时候,不同的知识模块,会自己建立相应的临时表存放从源数据库拉取的数据,再同步到我们的表里。
LASTUPDATE是后面加的,导致了ODI的临时表没有这个字段,从ODI的临时表导入我们表时,发现我们表多了LASTUPDATE字段,所以报错
解决:删除ODI建立的临时表重新进行同步
a2f140dc5ccaa356f1fd4a599dbbb785
83f9066de909fbcadf7ba113549e91ca
2、错误:ORA-01729: 需要数据库链接名
场景:模型能映射表结构到ODI,但是接口同步报错
解决:能映射表结构到ODI,说明数据服务器的JDBC连接到数据库端没问题,因为是不同数据库的同步,所以需要在红框中填入建好DBLINK,如果是本地同库不同schema可以直接用localhost
7d7871f81a45cebc4d6bd45712f19bf8
3、参数传入一直为空
场景:默认参数一直无法传入
解决:先将执行日志界别跳高到6,查看日志中参数传入的值是什么,如果已经有默认值单传入还是空的,可以查看参数->历史记录,把删掉里面的记录
ae90b55f0c1ba7c297ed8bcaf8cdeb97
db3405b2a8db2d88f616d8068273882d
e6e0d8b3c5fe92f96b7625a61a7e53e4

脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
--【主资料档案库】
--创建档案库表空间
CREATE TABLESPACE C##ODI_MASTER_TS
LOGGING
DATAFILE 'D:\Sortware\app\oracle\tablespace\apps\c##odi_master_ts.dbf'
SIZE 32M
AUTOEXTEND ON
NEXT 32M MAXSIZE 10G
EXTENT MANAGEMENT LOCAL;
--创建用户
CREATE USER C##ODI_MASTER IDENTIFIED BY "odi"
DEFAULT TABLESPACE C##ODI_MASTER_TS;
--授权
GRANT DBA TO C##ODI_MASTER;

--【开发工作资料档案库】
--创建用户
CREATE USER C##ODI_WORK IDENTIFIED BY "odi"
DEFAULT TABLESPACE C##ODI_MASTER_TS;
--授权
GRANT CONNECT TO C##ODI_WORK;
GRANT RESOURCE TO C##ODI_WORK;

--TARGET到SOURCE的DBLINK
CREATE DATABASE LINK SOURCE_DBL CONNECT TO SYSTEM IDENTIFIED BY 1234567 USING 'SOURCE';

--【SOURCE数据库】
--CREATE TABLE SOURCE_EMP
CREATE TABLE SOURCE_EMP(empno NUMBER NOT NULL
,ename VARCHAR2(20)
,job VARCHAR2(50)
,mgr NUMBER
,hiredate DATE
,sal NUMBER
,comm NUMBER
,deptno NUMBER
,lastupdate DATE DEFAULT SYSDATE NOT NULL);

--INSERT INIT DATA
INSERT INTO Source_emp
VALUES
(7369, 'SMITH', 'CLERK', 7902, To_Date('1980-12-17', 'YYYY-MM-DD'), 800.00, NULL, 20,SYSDATE);
INSERT INTO Source_emp
VALUES
(7499, 'ALLEN', 'SALESMAN', 7698, To_Date('1981-02-20', 'YYYY-MM-DD'), 1600.00, 300.00, 30,SYSDATE);
INSERT INTO Source_emp
VALUES
(7521, 'WARD', 'SALESMAN', 7698, To_Date('1981-02-22', 'YYYY-MM-DD'), 1250.00, 500.00, 30,SYSDATE);
INSERT INTO Source_emp
VALUES
(7566, 'JONES', 'MANAGER', 7839, To_Date('1981-04-02', 'YYYY-MM-DD'), 2975.00, NULL, 20,SYSDATE);
INSERT INTO Source_emp
VALUES
(7654, 'MARTIN', 'SALESMAN', 7698, To_Date('1981-09-28', 'YYYY-MM-DD'), 1250.00, 1400.00, 30,SYSDATE);
INSERT INTO Source_emp
VALUES
(7698, 'BLAKE', 'MANAGER', 7839, To_Date('1981-05-01', 'YYYY-MM-DD'), 2850.00, NULL, 30,SYSDATE);
INSERT INTO Source_emp
VALUES
(7782, 'CLARK', 'MANAGER', 7839, To_Date('1981-06-09', 'YYYY-MM-DD'), 2450.00, NULL, 10,SYSDATE);

--【TARGET数据库】
--CREATE TABLE TMP_TARGET_EMP
CREATE TABLE TMP_TARGET_EMP(empno NUMBER NOT NULL
,ename VARCHAR2(20)
,job VARCHAR2(50)
,mgr NUMBER
,hiredate DATE
,sal NUMBER
,comm NUMBER
,deptno NUMBER
,lastupdate DATE DEFAULT SYSDATE NOT NULL);
--CREATE TABLE TARGET_EMP
CREATE TABLE TARGET_EMP(empno NUMBER NOT NULL
,ename VARCHAR2(20)
,job VARCHAR2(50)
,mgr NUMBER
,hiredate DATE
,sal NUMBER
,comm NUMBER
,deptno NUMBER
,lastupdate DATE DEFAULT SYSDATE NOT NULL);

--【TEMP_TO_TARGET】
--将从SOURCE同步到TARGET的TMP_TARGET_EMP表的数据,增量同步到TARGET_EMP表
DECLARE
l_Lastupdate DATE;
l_Dummy_Nm NUMBER;
BEGIN
SELECT MAX(t.Lastupdate) INTO l_Lastupdate FROM Target_Emp t;

FOR Rec IN (SELECT *
FROM Tmp_Target_Emp s
WHERE s.Lastupdate > Nvl(l_Lastupdate, s.Lastupdate - 1)) LOOP

SELECT COUNT(1) INTO l_Dummy_Nm FROM Target_Emp t WHERE t.Empno = Rec.Empno;

IF l_Dummy_Nm = 0 THEN
INSERT INTO Target_Emp t VALUES Rec;
ELSE
UPDATE Target_Emp t SET ROW = Rec WHERE t.Empno = Rec.Empno;
END IF;
END LOOP;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
END;