oracle迁移达梦常见问题汇总
0、说明
本⽂主要结合之前⼀次oracle迁移达梦的项⽬, 将碰到的问题以及⼀系列踩过的坑列举出来供⼤家参考, 数据库版本是达梦7。(本⽂中涉及 到的部分对象名已⽤sch1,tab1等⽅式替换)
1、整体情况
迁移过程中失败任务数低于5%, ⼤部分对象和数据都能够保证正常迁移。其中对于出错的任务, 主要有导表和导函数包两部分。其中主要 棘⼿的在与迁移函数包等对象时的问题。
2、迁移错误详解
2. 1、通⽤问题
说明:对于直接使⽤DTS迁移失败的包, 最好从源端获取完整的定义, 重新核查报错原因 —— 避免编译通过后, 报错xxx 对象未在xxx 包中定义! (包头和包体不匹配:包头定义了三个函数, 在包体中, 可能只有两个函数)
达梦中的关键字可以在达梦SQL使⽤⼿册中查询, 也可以使⽤下⾯SQL查询:
select * from V$RESERVED_WORDS where RESERVED='Y';
所有正常的空格, 均会显⽰为:虚点; 如果是没有虚点的空⽩符, 即为异常的空⽩符 (常见于从邮件中、 ⽹页、QQ聊天框等中, 直接复制 出来的SQL)
2.2、表迁移问题
2.2. 1、标度⼤于精度
问题描述:
/* 任务失败: 创建表"sch1". "tab1" /
/ 第8 ⾏附近出现错误:
标度⼤于精度*/
/* 相关SQL语句: */
CREATE TABLE "sch1"."tab1"
(
"REGION_NAME" VARCHAR2(20) NULL,
"RATE" NUMBER(3,4) NULL,
"SCORE" VARCHAR2(20) NULL,
"CHECK_MONTH" VARCHAR2(20) NULL,
"INSERT_TIME" TIMESTAMP(0) NULL
);
解决⽅式:
达梦⾥⾯精度必须⼤于等于标度, 精度是总长度, 标度是⼩数位的长度, 按道理⼩数位不可能超过总体长度的 (但是oracle中并没有这个限 制) 。所以将NUMBER(3,4)改成NUMBER(4,4)即可。
2.2.2、局部唯⼀索引必须包含全部分区列
问题描述:
/* 任务失败: 创建表"sch1". "tab1" /
/ 第61 ⾏附近出现错误:
局部唯⼀索引必须包含全部分区列 /
/ 相关SQL语句: */
...
解决⽅法:
该问题是因为达梦分区表要求, 如果有主键, 必须包含在分区列中, 所以在迁移时需要设置映射关系, 将分区列映射为主键, 使⽤复合主键 的⽅式。
2.2.3、记录超长
问题描述:
/* 任务失败: 从"sch1". "tab1"迁移数据到"sch1". "tab1" /
/ 记录超长 /
解决⽅法:
dm7页⼤⼩设置成8k时, 所有字段加起来⽀持的最⼤长度是4k。所以这种问题需要在初始化数据时将页⼤⼩设置成16k或者32k。 或者使⽤STORAGE(USING LONG ROW) , 达梦在建表加上这个存储选项即可突破页⼤⼩限制。
2.2.4、Java heap space
问题描述:
/ 任务失败: 从"sch1". "tab1"迁移数据到"sch1". "tab1" /
/ Java heap space */
解决⽅法:
dts所在的机器内存不⾜导致。
2.2.5、违反协议
问题描述:
/* 任务失败: 从"sch1". "tab1"迁移数据到"sch1". "tab1" /
/ 违反协议 */
解决⽅法:
重新单独导⼊⼀遍即可。这个是oracle jdbc驱动报的错误, 原因未知, 可以试试在迁移⼯具⾥⾯指定最新的oracle jdbc驱动。
2.2.6、ORA-08103: 对象不再存在
问题描述:
/* 任务失败: 从"sch1". "tmp_ tab1"迁移数据到"sch1". "tmp_ tab1" /
/ ORA-08103: 对象不再存在
*/
解决⽅法:
该问题是因为导⼊的表是临时表, 所以导⼊数据时会出现这种问题, 重新导⼊即可解决。
2.3、函数包等对象问题
2.3. 1、语法分析出错
问题描述:
/* 任务失败: 创建⾃定义类型TY_SOFT_ WORK_ EXPERT_ OBJ /
/ 第3 ⾏, 第3 列[SECTION]附近出现错误:
语法分析出错*/
解决⽅法:
这类问题是因为在创建⾃定义类型时使⽤了DM7中的保留字, 只需要加上双引号即可。
2.3.2、⽆效的链接名
问题描述:
/* 任务失败: 创建视图"JTITSM". "CLOUD_ PERF_ CURRENT" /
/ 第6 ⾏附近出现错误:
⽆效的链接名[JTITSM_ CLOUD] */
解决⽅法:
该问题是因为使⽤到了dblink, ⽽在达梦中dblink未创建导致。
我们可以通过建⽴到⾃⾝的dblink, 暂时绕过依赖的问题, 但是⾃⾝上依然要有dblink对应的表结构, 没有的话, 就建⼀个。达梦创建 dblink⽅法可以参考:。
2.3.3、dbms_job⽆法使⽤
解决⽅法:
达梦中⽀持dbms_job包, 但是使⽤前要先启⽤:
SQL> SP_INIT_JOB_SYS(1);
2.3.4、dbms_job.submit使⽤报错:参数不匹配
问题描述:
解决⽅法:
因为达梦中dbms_job.submit需要匹配5个参数, 详细见达梦系统包使⽤⼿册。
2.3.5、⽆法修改与⾮键值保存表对应的列。
问题描述:
UPDATE
(
SELECT
A.STOP_PRODUCTION WRITE_STOP_PRODUCTION,
B.STOP_PRODUCTION READ_STOP_PRODUCTION
FROM
E_OUTPUT_HOUR A,
E_REPORT_HOUR B
WHERE
A.PE_ID = B.PE_ID
AND A.OUTPUT_ID = B.OUTPUT_ID
AND A.MEASURE_TIME = B.MEASURE_TIME
)
SET
WRITE_STOP_PRODUCTION = READ_STOP_PRODUCTION;
解决⽅法:
⽤A表去更新B表的数据, A表的关联条件必须为主键。 因此修改为:
UPDATE
E_OUTPUT_HOUR A
SET
A.STOP_PRODUCTION=B.STOP_PRODUCTION
from
E_REPORT_HOUR B
WHERE
A.PE_ID = B.PE_ID
AND A.OUTPUT_ID = B.OUTPUT_ID
AND A.MEASURE_TIME = B.MEASURE_TIME;
2.3.6、⽆效的对象名:TAB
问题描述:
SELECT COUNT(*)
INTO V_CNT
FROM TAB
WHERE UPPER(TNAME) = 'HIS_NE_ALARM_MSG'
OR UPPER(TNAME) = 'HIS_NE_ALARM_LIST';
解决⽅法:
⽅法1:
SELECT COUNT(*)
INTO V_CNT
FROM all_tables
WHERE UPPER(TABLE_NAME) = 'HIS_NE_ALARM_MSG'
OR UPPER(TABLE_NAME) = 'HIS_NE_ALARM_LIST';
⽅法2:
SELECT COUNT(*)
INTO V_CNT
FROM sysobjects
WHERE "SUBTYPE$"='UTAB'
and UPPER(NAME) = 'HIS_NE_ALARM_MSG'
OR UPPER(NAME) = 'HIS_NE_ALARM_LIST';
这⾥建议使⽤⽅法⼆, 直接查询sysobjects视图, DM中all_tables视图拼接的东西⽐较多。
2.3.7、⽆效的⽅法名: utl_encode.quoted_printable_encode
问题描述:
utl_raw.cast_to_varchar2(utl_encode.quoted_printable_encode(utl_raw.cast_to_raw(substr(subject,i)))) || '?=' ;
解决⽅法:
达梦中utl_encode包 只有BASE64_ENCODE 和BASE64_DECODE两种⽅法, 这⾥使⽤ BASE64_DECODE替换掉 quoted_printable_encode即可。
2.3.8、CURSOR⽆法作为查询项
问题描述:
procedure f1(p_staff_id staff.staff_id%type,
p_flow_id flow.flow_id %type,
flowCursor in out refCursor) is
begin
open flowCursor for
select b.tch_id,
b.TCH_NAME,
pkp_flow.getCurStaffName(b.STAFF_ID, b.person) as staff_name,
CURSOR (select d.tch_id, e.staff_name, d.TCH_NAME
from v_path c, v_tache d, staff e
where c.tch_id = d.TCH_ID
and (c.next_tch_id = b.tch_id or c.tch_id = b.TCH_ID)
and c.FLOW_ID = b.FLOW_ID
and d.STAFF_ID = e.staff_id)
from tache_notify_staffs a, v_tache b
where a.tch_id = b.tch_id
and a.flow_id = b.FLOW_ID
and a.staff_id = p_staff_id
and b.flow_path like p_flow_id || '/%'
and a.opinion is null;
end f 1 ;
解决⽅法:
达梦中⽆法⽀持此写法, 需在应⽤程序代码中实现修改, 这⾥先注释掉。
2.3.9、UTL_SMTP包⽆法使⽤
解决⽅法:
这个包在达梦新版本中已经实现, 打上补丁包, 然后调⽤系统过程创建该包。
SQL> SP_CREATE_SYSTEM_PACKAGES ( 1,'UTL_SMTP');
DMSQL executed successfully
used time: 17.984(ms) . Execute id is 259.
2.3. 10、UTL_I18N包⽆法使⽤
解决⽅法:
达梦中没有这个包, 因此⽆法使⽤, 通过在达梦中⾃定义⼀个和oracle中同名的包, 然后将需要⽤到的函数根据功能⼿动编写。主要⽤到 RAWTOHEX、HEXTORAW这两个函数来实现。
2.3. 1 1、DMBS_CRYPTO包⽆法使⽤
问题描述:
function encryptbyAes(input_string VARCHAR2,key VARCHAR2) return varchar2 IS
l_type pls_integer := dbms_crypto.encrypt_aes128 +
dbms_crypto.pad_pkcs5 +
dbms_crypto.chain_cbc;
l_encval raw(2000);
begin
l_encval := dbms_crypto.encrypt(
src=>utl_i18n.string_to_raw(input_string,'AL32UTF8') ,
typ=>l_type,
key=>utl_i18n.string_to_raw(key,'AL32UTF8'));
dbms_output.put_line(l_encval);
return l_encval;
end;
解决⽅法
因为达梦中没有该包, 上⾯oracle中该函数主要是实现将输⼊的内容进⾏加密, 然后返回加密的结果, 可以改写成:
function encryptbyAes(input_string VARCHAR2,key VARCHAR2) return varchar2 IS
ENCRYPTED_STRING VARCHAR2(2048);
l_encval VARCHAR2(2048);
begin
DBMS_OBFUSCATION_TOOLKIT .DESENCRYPT(
input_string, key, ENCRYPTED_STRING );
l_encval := ENCRYPTED_STRING;
dbms_output.put_line(l_encval);
return l_encval;
end;
2.3. 12、执⾏环境堆栈空间不⾜
解决⽅法:
修改参数VM_STACK_SIZE = 1024后不会包该错误, 但是会报嵌套层次太深的错误, 当前尚未解决。
2.3. 13、DMBS_SQL包使⽤问题
解决⽅法:
达梦DMBS_SQL包要使⽤DMBS_SQL.describe_columns获取列信息前需要先使⽤DBMS_SQL.execute将游标执⾏。
3、总结
整个迁移过程来看, ⼤部分问题都存在于函数包等对象上, 有些可以直接解决, 如关键字, ⽽有些涉及到oracle中系统包在达梦中不存在的 问题就需要⾃⼰想办法去解决, 例如修改代码。
除此之外, 迁移完成后可能会出现部分SQL在oracle运⾏速度正常, 但是在达梦中运⾏缓慢的情况, 这种情况我们还需要去调整数据库参数 和优化SQL。
文章
阅读量
获赞