oracle迁移达梦常见问题汇总

0、说明

本文主要结合之前一次oracle迁移达梦的项目,将碰到的问题以及一系列踩过的坑列举出来供大家参考,数据库版本是达梦7。(本文中涉及到的部分对象名已用sch1,tab1等方式替换)

1、整体情况

迁移过程中失败任务数低于5%,大部分对象和数据都能够保证正常迁移。其中对于出错的任务,主要有导表和导函数包两部分。其中主要棘手的在与迁移函数包等对象时的问题。
在这里插入图片描述

2、迁移错误详解

2.1、通用问题
说明:对于直接使用DTS迁移失败的包,最好从源端获取完整的定义,重新核查报错原因 —— 避免编译通过后,报错 xxx 对象未在 xxx 包中定义!(包头和包体不匹配:包头定义了三个函数,在包体中,可能只有两个函数)

2.1.1、关键词问题
a、关键词问题的处理方式
i、在包中手工改写,如,原先有变量名字为dateDiff,手动改写为“dateDiff”——用双引号屏蔽关键字。
ii、在客户端的配置文件(dm_svc.conf)中,配置对应关键字,迁移包时,不做改动,让驱动自动为我们做上述i中的事情。如下图即为配置屏蔽 TRACE和ROWS两个关键字:
在这里插入图片描述
达梦中的关键字可以在达梦SQL使用手册中查询,也可以使用下面SQL查询:

select * from V$RESERVED_WORDS where RESERVED='Y';

2.1.2、中文符号的问题
a、达梦的PLSQL中,不支持中文标点、异常空白符。(即不是空格、\r、\n的其他的空白符、不支持全角符号 —— 当成字符串处理的除外)
b、该空白符通过客户端工具,调整编辑器为显示空白字符,可以分别异常空白符
在这里插入图片描述
所有正常的空格,均会显示为:虚点;如果是没有虚点的空白符,即为异常的空白符(常见于从邮件中、网页、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方法可以参考:达梦创建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 f1;

解决方法:
达梦中无法支持此写法,需在应用程序代码中实现修改,这里先注释掉。

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.11、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。

发布了158 篇原创文章 · 获赞 91 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_39540651/article/details/105652785