ORACLE迁移GP实践

来源:互联网 发布:电脑淘宝没有登陆页面 编辑:程序博客网 时间:2024/06/06 02:07

https://www.cnblogs.com/gobird/p/3967373.html
最近在做oracle到greenplum的迁移实践,步骤如下:
1. 使用ora2pg实现Oracle的数据结构迁移到GP的实现过程
2. Oracle的数据迁移到GP的实现过程

  1. ora2pg的使用
    地址: https://github.com/darold/ora2p
    关系图如下:

需要安装DBD-oracle,DBD-pg,DBI模块,配置conf后可以把oracle的数据结构(table,view,package等)转化成PG的数据结构.也可以配置直接把oracle库的数据导入到PG里面.
环境参数:
OS RHEL6.5 64bit
Oracle client 10.2.0.5.0
GP 4.2.6.0
模块的参数在图上已经详细标注出来了.模块的安装标准的perl安装方法:
perl Makefile.PL
make
make test
make install

介绍一下配置文件:
复制代码
1 ORACLE_HOME /home/oracle/client_1
2 ORACLE_DSN dbi:Oracle:host=192.168.11.1;sid=orcl
3 ORACLE_USER manager
4 ORACLE_PWD tiger
5 SCHEMA test
6 TYPE TABLE VIEW PACKAGE COPY
7 PG_NUMERIC_TYPE 0
8 PG_INTEGER_TYPE 1
9 DEFAULT_NUMERIC float
10 SKIP fkeys pkeys ukeys indexes checks
11 NLS_LANG AMERICAN_AMERICA.UTF8
12 PG_DSN dbi:Pg:dbname=easyetl;host=127.0.0.1;port=5432
13 PG_USER easyetl
14 PG_PWD password
15 OUTPUT output.sql
复制代码
1-4 配置源端Oracle的信息

5 oracle的schema取值

6 准备转化的数据类型,也包括导数据的copy命令

7-9 用来转化oracle的number(p,s)到PG的类型:

7表示是否使用PG内部的数据类型,0表示不使用,1表示使用

8表示在7设置为0时,如果8设置为1,则类型number(p)的定义变更为integer;如果8设置为0,则number(p)也转化为numeric(p)

9表示是8设置为1的时候,类型number转化为float,如果8设置为0,则9不起作用.

简单的设置,如果7,8均设置为0,那么number(p) –> numeric(p),number(p,s) –> numeric(p,s), number –> numeric

10 约束们是否需要创建

11 语言选择

12-14 配置目的端PG(GP亦可),如果这三行信息不配置,也没关系,可以生成oracle转化为PG的脚本

15 生成文件

迁移中出现的情况:

(1) 表可以完全迁移过去

(2) 视图里面如果没有起别名的话,也需要手动添加别名

(3) package需要手动修改.注:ver13版本的package生成需要把perform/decode屏蔽掉,因为这二点未做好,模块为PLSQL.pm.

当然package转化不仅仅只是这部分东西,主要的有:

a 别名需要显式写出

b 隐式转化要显式写出

c 函数的差异(GP官方有一套Oracle的函数实现,基本上够用)

d oracle里面非标准写法,如: a left join b写成 a,b where a.xx=b.xx(+)

  1. Oracle的数据迁移到GP的实现过程

    使用sqluldr2把数据从oracle unload出来到一个named pipe上,然后通过gpload把数据载入到GP里面.
    sqluldr网址: http://www.anysql.net/tools/sqluldr_comming.html
    gpload参照文章: http://www.itpub.net/thread-1423310-1-1.html

dataload.sh
关键点有二个:
(1) sqluldr先生成数据,传到管道里面.gpload读取配置文件,从管道取数据,自己启动gpfdist,生成External table,载入GP库
(2) 当数据量少的时候,即sqluldr进程结束后,gpload进程还没完全启动.这个时候,gpload就一直等待管道里面的数据到来,hang住了.为了解决这个问题,特意在sqluldr的presql里面添加dbms_lock.sleep(2),这样就可以保证sqluldr进程结束前,gpload进程已经启动了.或者可以直接写c来指定管道是否堵塞来判断.
复制代码

!/bin/bash

if [ $# -lt 3 ];then
echo ‘Usage basename $0 pipe tablename control’
exit 1
fi

pipename=1tablename=2
control=3condition=4

mknod pipenamep/root/software/sqluldr2user=manager/tigerd@orclquery=selectfromtablename where conditionfield=0x7cfile=pipename
charset=utf8 text=CSV safe=yes persql=”begin dbms_lock.sleep(2); end;” &
gpload -f controllgpload.logrmrfpipename
复制代码

ora2gp.sh –生成control文件,包括管道文件名称.然后调用上述进程实现载入过程.
复制代码

!/usr/bin/env python

-- coding:utf-8 --

import yaml
import subprocess
import sys
import os

Script starts from here

paramnum=len(sys.argv)
datadt=20140820
condition=”1=1”

tplpath=”/root/template/”
pipepath=”/tmp/pipe”
batname=”/root/script/dataload.sh”

if (paramnum == 1):
print ‘Usage:’+ sys.argv[0]+’ tablename ’
sys.exit()
elif(paramnum == 2):
tablename=sys.argv[1]
elif(paramnum == 3):
tablename=sys.argv[1]
datadt=sys.argv[2]
elif(paramnum == 4):
tablename=sys.argv[1]
datadt=sys.argv[2]
condition=sys.argv[3]
else:
print ‘Usage:’+ sys.argv[0]+’ tablename datadt condition. (datadt condition is optional)!’
sys.exit()

pid=os.getpid()
pipename=pipepath+str(pid)

f = open(tplpath+”gp_template_load.ctl”)
dataMap = yaml.load(f)
f.close()

dataMap[‘GPLOAD’][‘INPUT’][0][‘SOURCE’][‘FILE’][0]=pipename
dataMap[‘GPLOAD’][‘OUTPUT’][0][‘TABLE’]=tablename
dataMap[‘GPLOAD’][‘INPUT’][6][‘ERROR_TABLE’]=tablename+’_err’

filename=tplpath+tablename+’.ctl’
f = open(filename,’w’)
yaml.dump(dataMap,f)
f.close()

handle=subprocess.Popen([batname,pipename,tablename,filename,condition])
handle.communicate()
复制代码
control文件模板
复制代码
VERSION: 1.0.0.1
DATABASE: dw
USER: manager
HOST: gp
PORT: 5432
GPLOAD:
INPUT:
- SOURCE:
LOCAL_HOSTNAME:
- gp
FILE:
- /tmp/mypipe
PORT_RANGE: [8001,9000]
- FORMAT: csv
- DELIMITER: ‘,’
- QUOTE: ‘”’
- HEADER: true
- ERROR_LIMIT: 10000
- ERROR_TABLE: tablename_err
OUTPUT:
- TABLE: tablename
- MODE: INSERT
PRELOAD:
- TRUNCATE: true

复制代码
后续操作:

上面的程序可以当作同步使用,但是真正的在生产使用就会有点不太让人放心.

原因有三:

(1)dataload.sh里面的sqluldr是放在后台处理的.当sqluldr出现异常,gpload可能会等待.当gpload出现异常的时候,sqluldr还是会载出文件.而且dataload.sh是fork出二个进程,当进程

出现异常,还需要手动寻找,kill掉.

(2)日常记录与处理.

(3)oracle与gp的表结构要严格一致才行.

基于此,写了可以统一处理fork的进程,增加了获取gp column list,加上日志处理这几部分.

oraconf文件格式:

CONFNAME:USER^PASS^TNSNAME

gpconf文件格式:

host:port:database:user:passwd

control文件看上面以及官方文档吧.

复制代码

!/bin/sh

. greenplum_loaders_path.sh
. setenv

if [ $# -lt 4 ];then
echo “Usage : basename $0 confname etl_date mode src_tbname tgt_tbname ”
echo ” confname : configuration at ${PWD}/conf/oraconf ”
echo ” etl_date : YYYYMMDD ”
echo ” mode : 1 truncate; 2 append”
echo ” src_tbname : oracle datasource tablename ”
echo ” tgt_tbname(optional) : greenplum datasource tablename”
exit 1
fi

trap the exception quit

trap ‘log_info “TERM/INTERRUPT(subprocess) close”;close_subproc’ INT TERM

declare -a sublist

function log_info()
{
DATETIME=date +"%Y%m%d %H:%M:%S"
echo -e “S DATETIMEP[]:*”| tee -a “LOGPATH"/"ETLDATE”/”$GPTABLE”.log
}

function collect_subproc()
{
local index
if [ {#sublist} -eq 0 ];then  
                index=0  
        else  
                index=
[{#sublist}]+1  
        fi  
        sublist[
index]=$1

}

function close_subproc()
{
for subid in sublist[@]dologinfokillprocessid:subid”
kill $subid
done
}

function parse_yaml()
{
local file=1localtablename=2
local pipename=3localetldate=4
sed -i -e “s/mypipe/”pipename"/"e"s/tablenameerr/public."tablename”_err/” -e “s/\

create and modify template for gpload use

log_info “create template “LOGPATH"/"ETLDATE”/”GPTABLE.ctl.cpTPLPATH"/gp_template_load_"MODE.ctlLOGPATH"/"ETLDATE/GPTABLE”.ctl
if [ ?ne0];thenloginfocreatetemplateLOGPATH"/"ETLDATE/GPTABLE”.ctl failed.”
exit 2
fi

parse_yaml “LOGPATH"/"ETLDATE”/”GPTABLE".ctlGPTABLE PIPENAMEETLDATE
if [ ?ne0];thenloginfomodifytemplateLOGPATH"/"ETLDATE/GPTABLE”.ctl failed.”
exit 2
fi

create pipename

log_info “create pipe /tmp/”PIPENAME.mknod/tmp/PIPENAME” p
if [ $? -ne 0 ];then
log_info “create pipe failed!”
exit 3
fi

gpload -f “LOGPATH"/"ETLDATE”/”GPTABLE".ctll"LOGPATH”/”ETLDATE"/"GPTABLE”.log &
collect_subproc !loginfounloadsql:selectcollist from ORATABLEsqluldr2user=ORACLE_USER"/"ORACLEPASS@ORACLE_SID" query="select collistfromORATABLE" head=Yes field=0x7c file=/tmp/"PIPENAMEcharset=gb18030text=CSVsafe=yespresql=begindbmslock.sleep(5);end;log=+LOGPATH"/"ETLDATE/GPTABLE”.log &
collect_subproc $!

wait
if [ ?ne0];thenloginfoGPTABLE load failed!”
else
log_info “GPTABLEloadsucc!filoginformrf/tmp/PIPENAME””
rm -rf /tmp/”PIPENAMEif[? -ne 0 ];then
log_info “rm /tmp/”$PIPENAME” failed.”
exit 4
fi
复制代码

分类: database,greenplum & postgresql
标签: greenplum

阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 写字楼是什么意思 张三丰异界游写字板 如何提高孩子写字速度 怎么教小朋友写字 小学生正确的写字姿势 梦见在黑板上写字 如何让孩子爱上写字 怎样才能提高孩子的写字速度 学生语文同步字帖写字课课练 什么软件可以在照片上写字 写实玛丽苏 超写实素描 写实素描 写实 超写实 写实油画 写实主义 写实的意思 写实彩铅画 写实派玛丽苏 写实女人体油画欣赏 写实派玛丽苏txt 陈丹青写实人体油画作品欣赏 冷军女性超写实人体油画 超写实素描高清照片 超写实素描高清图片 油画风景写实 油画写实风景 人体写实油画 极端写实女体油画 写实派玛丽苏by吕天逸 写实油画风景 写实派玛丽苏 吕天逸 写实风景油画教程 写实风景油画 写实油画人物 写实场景原画 培养考察写实情况主要优缺点 初中生写实记录范文10篇 学情分析怎么写 写情