• Oracle-expdp方式升级19c问题合集


    前言:

            最近在帮客户进行Oracle11g到19c版本的升级,使用expdp导用户的方式进行迁移,在升级过程中遇到了些错误问题,把当时的问题分析过程记录了下来,分享给大家。

    问题一:导入出现报错ORA-39346:

    1. ORA-39346: data loss in character set conversion for object COMMENT:"xxx_"
    2. ORA-39346: data loss in character set conversion for object COMMENT:"xxx_"
    3. ORA-39346: data loss in character set conversion for object COMMENT:"xxxFT"
    4. ORA-39346: data loss in character set conversion for object COMMENT:"xxxFT"
    5. ORA-39346: data loss in character set conversion for object COMMENT:"xxxFT"
    6. ORA-39346: data loss in character set conversion for object COMMENT:"xxxFT"
    7. ORA-39346: data loss in character set conversion for object COMMENT:"xxx"
    8. ORA-39346: data loss in character set conversion for object COMMENT:"xxx"

    问题分析:

    该报错说明在导入的过程字符集转化发生数据丢失的情况

    出现该问题是第一要做的就是确认源端和目标端的字符集(NLS_CHARACTERSET),国家字符集(NLS_NCHAR_CHARACTERSET)),操作系统NLS_LANG设置是否一致

    1. 1 select property_name,property_value
    2. 2 from database_properties
    3. 3* where property_name like '%CHARA%'
    4. PROPERTY_NAME PROPERTY_VALUE
    5. ------------------------------ ----------------------------------------
    6. NLS_NUMERIC_CHARACTERS .,
    7. NLS_NCHAR_CHARACTERSET UTF8
    8. NLS_CHARACTERSET AL32UTF8

    确认目标库和源端的字符集设置都一致排除字符集导致的问题之后,进一步查看报错对象的DDL元数据,发现源库存在中文乱码的情况,这从而导致在19c导入的创建对象的过程中出现ORA-39346: data loss in character set conversion的错误,实际对象创建成功,但乱码会出现字符转化错误

    问题解决:

            出现乱码丢失的都为注释,对应用的实际使用没影响,后续只能让应用自己慢慢去修改,不影响11g升级19c

    问题二:导入之后dba_jobs的log_user显示为SYS

            在导入job之后,检查发现dba_jobs的log_user字段为sys,而不是应用用户,priv_user,schema_user 这两个字段显示正常

     问题分析:

            一开始以为是使用sys导入的原因,尝试通过dbms_ijob手动创建,log_user还是显示为sys,后面通过Oracle 官方查看案例,才确认命中了bug 32249704,在19c通过impdp导入,log_user会发生改变

     问题解决:

           1  安装oneoff补丁32249704(online patch)修复了该问题

           2  也可以使用job的创建用户进行导出导入,规避该问题

    问题三:导入报错ORA-39083,ORA-01858

            导入发生物化视图刷新组创建失败的报错

    1. Processing object type SCHEMA_EXPORT/REFRESH_GROUP
    2. ORA-39083: Object type REFRESH_GROUP:"XXXX"."VW_XXXXX" failed to create with error:
    3. ORA-01858: a non-numeric character was found where a numeric was expected
    4. Failing sql is:
    5. BEGIN dbms_refresh.make
    6. (
    7. '"xxx"."xxx"',
    8. list=>null,
    9. next_date=>'00-JAN-01',
    10. interval=>'to_date( concat( to_char( sysdate+1,''dd-mm-yyyy''),'' 01:21:30''),''dd-mm-yyyy hh24:mi:ss'') ',
    11. implicit_destroy=>TRUE,
    12. lax=>FALSE,
    13. job=>52,
    14. rollback_seg=>NULL,
    15. push_deferred_rpc=>TRUE,
    16. refresh_after_errors=>FALSE,
    17. purge_option=>1,
    18. parallelism=>0,
    19. heap_size=>0
    20. );
    21. dbms_refresh.add(name=>'"xxx"."xxx"',list=>'"xxx"."xxx"',siteid=>0,export_db=>'xxx');
    22. END;
    23. /

     问题分析:

            dbms_refresh.make,  dbms_refresh.add是用于编译创建物化视图刷新组,刷新组调用的是job 52,执行出现报错的原因为需要数字的参数出现一个非数字的字符串,执行SQL的错误的地方在next_date=>'00-JAN-01',因为next_date的输入参数类型为date,但输入的字符串'00-JAN-02'没法隐式转化为日期,导致出现报错

    对于导入的执行SQL为啥会出现'00-JAN-02',我们查看job 52,可以发现job52在源库的状态为禁用(broken=y),导致next_date为4000-01-01 00:00:00,所以在导入的sql执行就变成next_date=>'00-JAN-01'

    问题解决:

    修改执行的sql,将next_date修改为日期类型to_date('4000-01-01 00:00:00','yyyy-mm-dd hh24:mi:ss'),在手动执行即可

    1. BEGIN dbms_refresh.make
    2. (
    3. '"xxx"."xxx"',
    4. list=>null,
    5. next_date=>to_date('4000-01-01 00:00:00','yyyy-mm-dd hh24:mi:ss'),
    6. interval=>'to_date( concat( to_char( sysdate+1,''dd-mm-yyyy''),'' 01:21:30''),''dd-mm-yyyy hh24:mi:ss'') ',
    7. implicit_destroy=>TRUE,
    8. lax=>FALSE,
    9. job=>52,
    10. rollback_seg=>NULL,
    11. push_deferred_rpc=>TRUE,
    12. refresh_after_errors=>FALSE,
    13. purge_option=>1,
    14. parallelism=>0,
    15. heap_size=>0
    16. );
    17. dbms_refresh.add(name=>'"xxx"."xxx"',list=>'"xxx"."xxx"',siteid=>0,export_db=>'xxx');
    18. END;
    19. /

    问题四:查询DBA_REFRESH字段broken出现“?”

    1. 1* select ROWNER,RNAME,REFGROUP,JOB,BROKEN,job from DBA_REFRESH
    2. ROWNER RNAME REFGROUP JOB B JOB
    3. ------------------------------ -------------------------------------------------------------------------------------------------------------------------------- ---------- ---------- - ----------
    4. xxx xxx_MAIN_TAGS 12 ?
    5. xxx xxx_CATEGORY_NAMES 10 ?
    6. xxx xxx_READ_TIMES 16 ?
    7. xxx xxx_ORG_DEPT_NAMES 15 ?
    8. xxx xxx_READER_USERS 13 ?
    9. xxx xxx_ATT_DOWN_USERS 9 ?
    10. xxx xxx_COMMENT_TIMES 11 ?
    11. xxx xxx_USER_HAS 17 ?
    12. xxx xxx_USER_NO 14 ?

    问题分析:

    ​        查看DBA_REFERSH视图的定义SQL,可以发现broken等于?的条件为decode(bitand(j.flag,1),1,'Y',0,'N','?') AS BROKEN

    1. SELECT ROWNER,
    2. RNAME,
    3. REFGROUP,
    4. IMPLICIT_DESTROY,
    5. PUSH_DEFERRED_RPC,
    6. REFRESH_AFTER_ERRORS,
    7. ROLLBACK_SEG,
    8. JOB,
    9. NEXT_DATE,
    10. INTERVAL,
    11. BROKEN,
    12. PURGE_OPTION,
    13. PARALLELISM,
    14. HEAP_SIZE,
    15. JOB_NAME
    16. FROM (
    17. SELECT r.owner AS ROWNER, r.name AS RNAME, r.REFGROUP AS REFGROUP,
    18. decode(bitand(r.flag,1),1,'Y',0,'N','?') AS IMPLICIT_DESTROY,
    19. decode(bitand(r.flag,2),2,'Y',0,'N','?') AS PUSH_DEFERRED_RPC,
    20. decode(bitand(r.flag,4),4,'Y',0,'N','?') AS REFRESH_AFTER_ERRORS,
    21. r.rollback_seg AS ROLLBACK_SEG,
    22. j.JOB AS JOB, j.NEXT_DATE AS NEXT_DATE, j.INTERVAL# AS INTERVAL,
    23. decode(bitand(j.flag,1),1,'Y',0,'N','?') AS BROKEN,
    24. r.purge_opt# AS PURGE_OPTION,
    25. r.parallelism# AS PARALLELISM,
    26. r.heap_size# AS HEAP_SIZE,
    27. r.job_name AS JOB_NAME
    28. FROM rgroup$ r, job$ j
    29. WHERE r.instsite = 0
    30. AND r.job_name IS NULL AND r.job = j.job(+)
    31. UNION ALL
    32. SELECT r.owner AS ROWNER, r.name AS RNAME, r.REFGROUP AS REFGROUP,
    33. decode(bitand(r.flag,1),1,'Y',0,'N','?') AS IMPLICIT_DESTROY,
    34. decode(bitand(r.flag,2),2,'Y',0,'N','?') AS PUSH_DEFERRED_RPC,
    35. decode(bitand(r.flag,4),4,'Y',0,'N','?') AS REFRESH_AFTER_ERRORS,
    36. r.rollback_seg AS ROLLBACK_SEG,
    37. r.JOB AS JOB,
    38. CAST(s.next_run_date AS DATE) AS NEXT_DATE,
    39. substr(s.repeat_interval,1,200) AS INTERVAL,
    40. decode(s.enabled,'FALSE','Y','TRUE','N','?') AS BROKEN,
    41. r.purge_opt# AS PURGE_OPTION,
    42. r.parallelism# AS PARALLELISM,
    43. r.heap_size# AS HEAP_SIZE,
    44. r.job_name AS JOB_NAME
    45. FROM rgroup$ r, dba_scheduler_jobs s
    46. where r.instsite = 0
    47. AND r.owner = s.owner(+)
    48. and r.job_name IS NOT NULL AND r.job_name = s.job_name(+)
    49. )

     j.flag字段来着于基表job$,但查看基表job$的数据,可以发现job$没有数据,由于job$没有数据,导致于rgroup$左连接之后,字段j.flag返回null,所以显示为?

    1. SQL> select count(*) from job$;
    2. COUNT(*)
    3. ----------
    4. 0

     问题解决:

            从官方上看,没有关于Oracle19c基表job$没有数据的说明,也没有相关的公开bug说明,目前的规避方法只能通过rgroup$与dba_jobs进行关联查询规避问题

    问题五:导入出现ORA-02298: cannot validate (XXXX.FK82xxx0705) - parent keys not found

    1. Failing sql is:
    2. ALTER TABLE "xxx"."xxx" ADD CONSTRAINT "FKxxx" FOREIGN KEY ("FD_DOC_ID") REFERENCES "xxx"."xxxx" ("xxxx") ENABLE
    3. ORA-39083: Object type REF_CONSTRAINT:"xxx"."xxxx" failed to create with error:
    4. ORA-02298: cannot validate (xxx.xxxx) - parent keys not found
    5. Failing sql is:
    6. ALTER TABLE "xxx"."xxxx" ADD CONSTRAINT "xxxx" FOREIGN KEY ("xxxx") REFERENCES "xxx"."SYS_NOTIFY_TODO" ("xxxx") ENABLE
    7. ORA-39083: Object type REF_CONSTRAINT:"xxx"."xxxx" failed to create with error:
    8. ORA-02298: cannot validate (xxx.xxxx) - parent keys not found

    问题分析:

            出现外键约束检查失败之后,首先需要检查的是父表以及子表的约束状态是否正常

    1. select constraint_name,status
    2. from dba_constraints
    3. select b.owner, b.table_name, c.column_name FK_column, b.constraint_name, b.delete_rule
    4. from dba_constraints a, dba_constraints b, dba_cons_columns c
    5. where a.owner = b.r_owner and
    6. b.owner = c.owner and
    7. b.table_name = c.table_name and
    8. b.constraint_name = c.constraint_name and
    9. a.constraint_name = b.r_constraint_name and
    10. b.constraint_type = 'R' and
    11. a.owner = '' and
    12. a.table_name in ('') and
    13. a.constraint_type = 'P';

     如果检查约束状态正常,则很有可能是导出父表以及子表的数据不一致导致,即子表的外键出现父表不存在的数据,导致在添加外键约束的时候,检查不通过

    问题解决:

            expdp导出的时候,添加flashback_scn确保导出数据时间点一致

    1. ---查看数据库的当前scn
    2. select to_char(current_scn) from v$database;
    3. ---expdp 添加
    4. FLASHBACK_SCN=

    问题六:导入对象权限出现丢失

            在导入完成之后,比较对象权限两边的数量,出现目标端权限少于源端权限的情况

    问题分析:

            通过对两边对象权限进行比对,发现缺失的授权对象都是sys对象

    通过Oracle官方查看,用户不导出SYS对象的授权是expdp预期的行为,不是bug或是错误,(PS:这里只能说明自己的方案还不够谨慎!!!)

    问题解决:

            在源库手动生成批量授权的语句,在导目标库进行导入

    1. 1. As the privileges on SYS owned objects are not exported, you need to have another method in place which re-creates these privileges. E.g. a script that is called during export time and that will recreate these grants (or you store these lines in a table).
    2. Example:
    3. connect / as sysdba
    4. spool grants_tc.out
    5. col GRANTS for a80
    6. -- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    7. -- Add below the users and/or roles as appropriate for GRANTEE
    8. -- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    9. select 'grant ' || privilege || ' on ' ||'"'||table_name ||'"'||
    10. ' to ' || grantee || ';' "GRANTS"
    11. from dba_tab_privs
    12. where owner = 'SYS' and privilege not in ('READ', 'WRITE')
    13. and grantee in ('TC')
    14. order by 1;
    15. spool off
    16. -- example of query output:
    17. GRANTS
    18. --------------------------------------------------------------------------------
    19. grant EXECUTE on DBMS_CRYPTO to TC;
    20. 2. Before the start of the Import Data pump job, you can pre-create the schema, e.g.:
    21. $ impdp system/<PASSWORD> directory=<DIRECTORY NAME> dumpfile=<FILENAME>.dmp logfile=<LOG FILE NAME>..log schemas=tc include=user
    22. 3. Then pre-create the grants on SYS owned objects, by running your script (see step 1 above).
    23. 4. Followed by the import of the rest of the objects, e.g.:
    24. $ impdp system/<PASSWORD> directory=<DIRECTORY NAME> dumpfile=<FILE NAME>.dmp logfile=<LOG FILE NAME>.log schemas=tc exclude=user

    总结:

        ​    ​以上为在expdp方式11g升级19c遇到的错误合集,希望对大家有所帮助!

  • 相关阅读:
    Java核心编程(18)
    SpringBoot自动装配
    C语言力扣第32题之最长有效括号。用栈实现
    【大数据】Spark使用大全:下载安装、RDD操作、JAVA编程、SQL
    数据结构与算法-第五章 树与二叉树
    线上频繁fullgc问题-SpringActuator的坑
    人大金仓数据库创建与还原--九五小庞
    Netty架构详解
    Flutter学习笔记 --事件处理
    vite创建Vue3项目:router+pinia+element-plus or antd + sass + ts
  • 原文地址:https://blog.csdn.net/sinat_36757755/article/details/126862152