Oracle到DB2的移植挑战和问题总结.docx
- 文档编号:9978885
- 上传时间:2023-02-07
- 格式:DOCX
- 页数:22
- 大小:22.57KB
Oracle到DB2的移植挑战和问题总结.docx
《Oracle到DB2的移植挑战和问题总结.docx》由会员分享,可在线阅读,更多相关《Oracle到DB2的移植挑战和问题总结.docx(22页珍藏版)》请在冰豆网上搜索。
Oracle到DB2的移植挑战和问题总结
Oracle到DB2的移植挑战和问题总结
一、评估阶段
挑战:
不能很好的评估出移植所需的工作量和技术难点。
主要问题:
1)合作伙伴配合力度较差,很难找到合适的人员对IBM的移植工作进行支持。
2)项目陈旧,难于找到熟悉系统的开发人员。
3)有时刚开始接触不到要移植的系统。
4)有些问题MEET2不能发现。
5)制定的移植范围过大,不够明确。
如何解决:
1)多和系统开发人员沟通,了解系统中所有关于数据库操作的部分。
2)评估的时候能访问Oracle的系统,用IDMT导出全部Oracle脚本,用MEET2进行分析。
3)根据经验,检查脚本里那些IDMT查不出来的地方。
4)总结出所有要修改的对象,算出工作量。
编写移植评估报告,确定移植范围,最好能精确到模块。
二、数据库移植阶段
挑战:
1)当前最新版本DB29.7.3在兼容性方面还存在诸多的问题,在移植的过程中经常会碰到很多未知的问题。
2)对于PL/SQL的移植,花费精力大,测试难,容易出错。
3)IDMT里某个对象部署成功,不代表该对象移植成功。
主要问题和修改方法:
1)DB2还不支持嵌套函数和嵌套存储过程,此修改是最耗时同时最容易出问题的地方。
2)DB2里对FUNCTION的支持还比较弱,虽然已经支持OUT参数,但是调用方式必须是标准的赋值操作。
虽然改法简单,不容易出错,但是有可能代码里大量用到,修改工作量可能会很大。
3)PL/SQL的package定义里还不支持JavaFunction。
这个问题需要将JavaFunction提取出来放到DB2的module里,同时为了支持OUT参数,需要将JavaFunction改成Procedure。
Javafunction代码的提取,转换部署部分已经做完,因为将Function改成了Procedure,Java代码的return值要去掉,同时OUT类型参数要变成数组类型。
4)DB2在部署的时候会经常碰到DB2Crash的问题。
5)有些Oracle的内置包在DB2里不支持,比如DBMS_AQ,DBMS_APPLICATION_INFO,虽然有模拟Oracle的类似实现,但是功能不全,可能会有一些bug在里面。
6)对于NUMBER,VARCHAR2,DATE类型,在DB2系统表里存储的时候会转成DB2的类型,因此如果代码用到了类型比较就会出问题。
7)不能支持多action的trigger,需要转成多个trigger。
解决方法:
1)如果PL/SQL程序较多,分析出PL/SQL之间的调用关系,逐层移植
2)遍历代码,优先移植那些代码里用到的PL/SQL程序包
3)两阶段修改,第一阶段保证所有对象部署可以成功,第二阶段修改那些部署成功但是状态是无效的对象。
三、应用移植阶段
挑战:
1)有些基于标准接口的行为Oracle和DB2是不同的。
2)应用程序里用到的SQL是经过封装或者拼接出来的。
主要问题和修改方法:
1)OracleOCCI接口不能兼容,需要自己根据DB2CLI模拟OracleOCCI接口。
2)DB2973不兼容JDK1.4的NUMBER数据类型,需要升级到JDK1.5或以上版本
3)DB2JDBC里不能使用callfunction()的命令来调用function,所有function都要封装成procedure。
4)有些JDBC接口Oracle和DB2行为不同,比如executeQuery等。
解决方法:
1)争取原开发人员可以介入一起修改。
2)总结出可以批量修改的地方,进行批量修改。
3)争取一套代码兼容Oracle和DB2。
4)总结出核心业务,优先移植。
四、测试阶段
挑战:
1)移植后的数据库对象难于独立测试。
2)不熟悉业务和代码,IBM的人员难于对应用程序进行测试和问题定位。
3)对于系统架构和性能调整不熟悉。
解决方法:
1)原测试人员介入协助测试和问题定位,IBM的人员负责解决定位后的问题。
2)原测试人员总结出核心业务,优先测试。
附录1:
DB2V973主要问题修改方法总结
主要修改的问题1:
DB2还不支持嵌套函数和嵌套存储过程。
此修改是最耗时同时最容易出问题的地方。
代码如下所示:
CREATEORREPLACEPACKAGEBODYTESTNESTED
AS
PROCEDUREA2
(
l_inINNUMBER,
l_outOUTNUMBER
)
AS
l_rtNUMBER;
Xvarchar2(10):
='empty';
FUNCTIONA1
RETURNNUMBER
AS
BEGIN
l_out:
=l_out+l_in+1;
RETURN1;
ENDA1;
BEGIN
l_out:
=2;
l_rt:
=A1();
DBMS_OUTPUT.PUT_LINE('l_out='||l_out);
ENDA2;
ENDTESTNESTED;
修改方法:
将嵌套函数和过程外提,同时将子函数里用到的复函数的内部变量外提到package级。
如果子函数用到父函数的参数,则将父函数的参数作为子函数的参数,同时OUT改为INOUT。
修改后的代码如下所示:
CREATEORREPLACEPACKAGEBODYTESTNESTED
AS
l_rtNUMBER;
Xvarchar2(10):
='empty';
FUNCTIONA1
(
l_inINNUMBER,
l_outINOUTNUMBER
)
RETURNNUMBER
AS
BEGIN
l_out:
=l_out+1;
RETURN1;
ENDA1;
PROCEDUREA2
(
l_inINNUMBER,
l_outOUTNUMBER
)
AS
BEGIN
l_out:
=2;
l_rt:
=A1(l_in,l_out);
DBMS_OUTPUT.PUT_LINE('l_out='||l_out);
ENDA2;
ENDTESTNESTED;
主要修改的问题2:
DB2里对FUNCTION的支持还比较弱,虽然已经支持OUT参数,但是调用方式必须是标准的赋值操作。
虽然改法简单,不容易出错,但是代码里可能大量用到,修改工作量可能很大。
原先的调用方式
IFPa_Sql.rec_count(l_sql,l_cnt)<>0THEN
Pa_Msgs.put_msg(pi_func_id,'COMMON','0000000091','Pa_Sql.rec_count');
RETURN4;
ENDIF;
需要修改为:
l_rt:
=Pa_Sql.rec_count(l_sql,l_cnt);
IFl_rt<>0THEN
Pa_Msgs.put_msg(pi_func_id,'COMMON','0000000091','Pa_Sql.rec_count');
RETURN4;
ENDIF;
主要修改的问题3:
PL/SQL的package定义里还不支持JavaFunction。
这个问题需要将JavaFunction提取出来放到DB2的module里,同时为了支持OUT参数,需要将JavaFunction改成Procedure。
Javafunction代码的提取,转换部署部分已经做完,因为将Function改成了Procedure,Java代码的return值要去掉,同时OUT类型参数要变成数组类型。
修改之前代码如下:
FUNCTIONONL_INTF_GET_CUST_INFO_J(PI_TRAN_NOINVARCHAR2,
PI_BCH_CDEINVARCHAR2,
PI_TELL_IDINVARCHAR2,
PI_TRACK_NOINVARCHAR2,
PI_CURR_DATEINVARCHAR2,
PI_ID_TYPINVARCHAR2,
PI_ID_NOINVARCHAR2,
PI_INTF_PATHINVARCHAR2,
PI_XML_FILE_NAMINVARCHAR2,
PO_CHI_NAMOUTVARCHAR2,
PO_CUST_LEVELOUTVARCHAR2,
--STARTAddbycota2008-11-12
PO_CUST_NOOUTVARCHAR2,
--ENDAddbycota2008-11-12
PO_ERR_MSGOUTVARCHAR2)RETURNNUMBERIS
LANGUAGEJAVANAME'com.excelsoft.bo.BOMain.online_Cust_Info_Query(java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String[],java.lang.String[],java.lang.String[],java.lang.String[])returnint';
修改后的代码如下:
CREATEORREPLACEMODULEPA_INTF_J;
ALTERMODULEPA_INTF_JPUBLISHPROCEDUREONL_INTF_GET_CUST_INFO_J(
INPI_TRAN_NOVARCHAR2(4000),
INPI_BCH_CDEVARCHAR2(4000),
INPI_TELL_IDVARCHAR2(4000),
INPI_TRACK_NOVARCHAR2(4000),
INPI_CURR_DATEVARCHAR2(4000),
INPI_ID_TYPVARCHAR2(4000),
INPI_ID_NOVARCHAR2(4000),
INPI_INTF_PATHVARCHAR2(4000),
INPI_XML_FILE_NAMVARCHAR2(4000),
OUTPO_CHI_NAMVARCHAR2(4000),
OUTPO_CUST_LEVELVARCHAR2(4000),
OUTPO_CUST_NOVARCHAR2(4000),
OUTPO_ERR_MSGVARCHAR2(4000)
)
FENCED
LANGUAGEJAVA
PARAMETERSTYLEJAVA
EXTERNALNAME'com.excelsoft.bo.BOMain.online_Cust_Info_Query'
NOEXTERNALACTION;
主要修改的问题4:
DB2JDBC不能使用?
:
=call的方式来调用用户自定义函数。
由于JAVA代码里全部使用这种方式来调用,并且PL/SQL的package里几乎全都是用户自定义函数,所以现在的一个修改方法是为每一个用户自定义函数都封装一个procedure,将函数的return值作为procedure的第一个参数,这样只要在代码里修改调用的名字就可以,其他不必修改。
封装后procedure已经由程序自动生成。
封装后的代码:
CREATEORREPLACEPACKAGEBODYWRAPPER_CIB_LOS_INS_ELSAS
PROCEDURELOS_INS_LOAN_ACC_INFO(COUTNUMBER,PI_INSTTU_CDEINVARCHAR2,PI_LOAN_TYPINVARCHAR2,PI_LOAN_NOINNUMBER)IS
BEGIN
c:
=CIB_LOS_INS_ELS.LOS_INS_LOAN_ACC_INFO(PI_INSTTU_CDE
PI_LOAN_TYP,PI_LOAN_NO);
END;
END;
@
主要修改的问题5:
DB2JDBC不能识别函数作为列名的SQL语句。
DB2里必须在函数后面加AS字句才能识别。
代码里用的最多的地方是分页用的ROWID,需要熟悉的开发人员进行代码的修改,否则所有涉及分页的页面都无法显示。
修改前的代码:
ResultSetrs;
Statementstmt=conn.createStatement();
rs=stmt.executeQuery("selectROWIDfromtestt");
rs.next();
System.out.println(rs.getString("ROWID"));
System.out.println("executesuccess");
System.out.println();
rs.close();
stmt.close();
conn.close();
修改后的代码:
ResultSetrs;
Statementstmt=conn.createStatement();
rs=stmt.executeQuery("selectROWIDasROWIDfromtestt");
rs.next();
System.out.println(rs.getString("ROWID"));
System.out.println("executesuccess");
rs.close();
stmt.close();
conn.close();
主要修改的问题6:
JDK1.4不能兼容部分DB2V973的PL/SQL语法,需要升级成JDK1.5或者以上版本。
比如会出现decfloat转型错误,代码如下所示
publicstaticvoidmain(Stringargs[]){
try{
Class.forName("com.ibm.db2.jcc.DB2Driver");
Connectionconn=DriverManager.getConnection(
"jdbc:
db2:
//192.168.0.1:
50000/NJXC","loan_admin",
"lipsadmin");
CallableStatementcs=null;
cs=conn.prepareCall("callpa_workflow_wrapper.F_LOCK_WORKFLOW(?
?
?
?
?
?
)");
cs.setLong(2,15546);
cs.setString(3,"LOS");
cs.setString(4,"N");
cs.setString(5,"LOAN_ADMIN");
cs.registerOutParameter(1,Types.NUMERIC);
cs.registerOutParameter(6,Types.VARCHAR);
cs.execute();
System.out.println(cs.getInt
(1));
}catch(Exceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
}
主要修改的问题7:
部署的时候DB2Crash
解决方法
1)增大AGENT_STACK_SZ。
2)减少procedure的overload。
其它问题:
1.不能创建类型为table和object的自定义类型。
不支持的代码如下:
CREATEORREPLACETYPE"LOAN_ADMIN"."T_ARRAY_LOG_QUEUE"ASTABLEOFT_LOG_QUEUE;
修改方法:
需要将table和object类型的自定义类型封装到Package里,代码如下:
CREATEORREPLACEPACKAGE"LOAN_ADMIN"."PA_TYPES"AS
TYPE"SMP_VDE_EVT_OCC_OBJECT"ISRECORD(
eventIdINTEGER,
targetNameVARCHAR2(128)
);
TYPE"ARRAY_TYPE_THREAD"ISTABLEofTYPE_THREADINDEXBYINTEGER;
ENDPA_TYPES;
2.数据库表里的SYS.ANYDATA类型的字段不支持。
修改方法:
将ANYDATA类型修改为VARCHAR2类型
3.CreateView里不能加OrderBy子句。
修改方法:
改成createviewabcasselect*from(selectc1froma1orderbyc1)的形式
4.部分package部署导致DB2Crash。
修改方法:
db2updatedbmcfgusingAGENT_STACK_SZ200
或者降低overload函数的数量。
5.RecordtypedoesnotsupportBOOLEANanddefaultvalue
LanguageinPL/SQLthatwedonotsupport
CREATEORREPLACEPACKAGETESTIS
TYPELOG_CTXISRECORD(
isDefaultInitBOOLEANdefaultFALSE
);
END;
修改方法:
YoucanuseanINTEGERwith0and1.DEFAULTisnotsupportedtoday.YouneedtoinitializeexplicitlyifNULLisnotacceptable.
6.UpdateCursor不能加commit语句,否则数据库会报错。
7.DBMS_APPLICATION.INFO和DBMS_AQ的包在DB2973里还不支持。
修改方法:
模拟Oracle在DB2里创建了同样名称,同样功能的包。
8.LTRIM(x,y)和RTRIM(x,y)函数在DB2里不支持。
修改方法:
使用java模拟oracle的ltrim和rtrim方法,创建同名的函数。
9.selectcount(rowid)intoxxxfromxxx不支持。
修改方法:
selectcount(*)intoxxxfromxxx
10.Package不支持SYS_开头的函数名。
修改前:
FUNCTIONSYS_DATERETURNDATE;
修改方法:
增加F_的前缀
FUNCTIONF_SYS_DATERETURNDATE;
11.中文环境下NEXT_DAY函数无效。
修改方法:
重写NEXT_DAY函数
CREATEORREPLACEFUNCTIONNEXT_DAY
(
i_dateINDATE,
i_day_nameINVARCHAR2
)
RETURNDATE
AS
L_DAYOFWEEK_1INTEGER;
L_DAYOFWEEK_2INTEGER;
L_NEWDAYDATE;
BEGIN
L_DAYOFWEEK_1:
=dayofweek_iso(i_date);
IFi_day_name='MONDAY'ori_day_name='MON'THENL_DAYOFWEEK_2:
=1;ENDIF;
IFi_day_name='TUESDAY'ori_day_name='TUE'THENL_DAYOFWEEK_2:
=2;ENDIF;
IFi_day_name='WEDNESDAY'ori_day_name='WED'THENL_DAYOFWEEK_2:
=3;ENDIF;
IFi_day_name='THURSDAY'ori_day_name='THU'THENL_DAYOFWEEK_2:
=4;ENDIF;
IFi_day_name='FRIDAY'ori_day_name='FRI'THENL_DAYOFWEEK_2:
=5;ENDIF;
IFi_day_name='SATURDAY'ori_day_name='SAT'THENL_DAYOFWEEK_2:
=6;ENDIF;
IFi_day_name='SUNDAY'ori_day_name='SUN'THENL_DAYOFWEEK_2:
=7;ENDIF;
IF(L_DAYOFWEEK_2-L_DAYOFWEEK_1)>0THENL_NEWDAY:
=i_date+(L_DAYOFWEEK_2-L_DAYOFWEEK_1);ENDIF;
IF(L_DAYOFWEEK_2-L_DAYOFWEEK_1)<0or(L_DAYOFWEEK_2-L_DAYOFWEEK_1)=0THENL_NEWDAY:
=i_date+(7+L_DAYOFWEEK_2-L_DAYOFWEEK_1);ENDIF;
RETURNL_NEWDAY;
END;
12.JDBC里查询列表含有CLOB字段不能使用scrollableresultset。
修改方法:
从查询列表里去掉CLOB字段或者将CLOB改成varchar
13.含有insert/update/delete语句的function不能使用commit。
修改方法:
去掉commit或者改成procedure
14.to_char(sysdate,fmDAY)不支持
修改方法:
改成to_char(sysdate,DAY)
15.executeimmediate‘altersessionsetnls_date_language="AMERICAN"‘不支持。
修改方法:
改成executeimmediate'setcurrentlocaleLC_TIME=''en_US'''
16.GRANTSELECTON
修改方法:
改成GRANTSELECTONSEQUENCE
17.DBMS_SQL.PARSE()函数里的SQL语句前面不能有空格。
18
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Oracle DB2 移植 挑战 问题 总结