在做一套库的迁移准备,测试的时候有些异常,记录一下处理办法。 如果有处理不对的地方,请不吝赐教。
1.dba_objects表对比发现LOB对象数量差距大
数据泵迁移完对比对象数量,发现LOB对象差距很大。
目标库执行查询:
代码语言:javascript复制--查询目标库数据
select object_type, count(*) as num
from dba_objects
where owner = 'LC'
group by object_type
--查询源库数据,通过dblink
select object_type, count(*) as num
from dba_objects@qy
where owner = 'LC'
group by object_type
查询结果,相差1070个LOB对象:
由于只是迁移测试,并没有停业务,所以首先想到的是不是在迁移完成到对比数据之间的时间之间,创建了大量的LOB对象呢?
代码语言:javascript复制--目标库执行查询
select object_type, object_name, status, created
from dba_objects@qy
where object_type = 'LOB'
order by CREATED desc;
查询结果,没有新创建LOB:
对象的状态(VALID/INVALID)并不会影响导入,这点不需要验证。
到这里就没思路了,有大佬提示查询mos,在1595391.1中找到答案: 含有lob字段的表drop掉之后,lob字段实际并没有purged,而是放在回收站中。这种情况下,查询dba_object(包含user_object和obj)仍然能看到删掉的lob对象。准确的对比方式应该是查询user_lobs表。
我们分别查询user_lobs表跟user_recyclebin表:
代码语言:javascript复制select count(*) from user_lobs;
select count(*) from user_lobs@qy;
user_lobs的结果:
代码语言:javascript复制 select count(*) from user_recyclebin@qy where type='LOB';
源库user_recyclebin的结果:
最后:
- 源库回收站中1070 user_lobs中360=1430,这样就跟dba_objects表的数量对起来了,所以这部分忽略即可
- obj表是user_objects视图的同义词
--dba_objects表中查看obj的类型
select * from dba_objects where object_name='OBJ';
--查看同义词创建语句
select dbms_metadata.get_ddl('SYNONYM','OBJ','PUBLIC') from dual;
--查询结果
CREATE OR REPLACE PUBLIC SYNONYM "OBJ" FOR "SYS"."USER_OBJECTS"
- dba_lobs=all_lobs,官方文档说明
DBA_LOBS displays the BLOBs and CLOBs contained in all tables in the database. BFILEs are stored outside the database, so they are not described by this view. This view’s columns are the same as those in ALL_LOBS.
https://docs.oracle.com/en/database/oracle/oracle-database/12.2/refrn/ALL_LOBS.html#GUID-EA28B5D0-3C72-4D7A-9151-AD96A132FDE5
2.源库有5条索引没有导入目标库
导入完成对比数据发现差了5条索引,但是导入日志并没有报错,排查的思路是
- 先查看日志是否有错误抛出
- 找出差异的是哪几条索引
- 检查索引的ddl语句、依赖的表等信息
首先检查日志未发现报错
通过minus方式对比dba_indexes表找出具体索引:
代码语言:javascript复制--migrate_username是源库创建的待迁移用户表,在XTTS迁移那篇里有建表语句
--SYS_C开头的索引是主键索引,DBA_CONSTRAINTS表里可以确认到
--SYS_IL开头的索引是LOB字段自动创建的索引
SELECT owner, index_name, INDEX_TYPE
FROM dba_indexes@qy
WHERE OWNER IN (SELECT username FROM SYSTEM.migrate_username@qy)
AND index_name NOT LIKE 'SYS_C%'
AND index_name NOT LIKE 'SYS_IL%'
MINUS
SELECT owner, index_name, INDEX_TYPE
FROM dba_indexes
WHERE OWNER IN (SELECT username FROM SYSTEM.migrate_username@qy)
ORDER BY owner, index_name;
查询结果:
随便找一条,看看创建语句;
代码语言:javascript复制SQL> set long 9999
SQL> select dbms_metadata.get_ddl('INDEX','PBXXXX_X','LC') from dual;
查询结果:
可以看出索引是LC用户的对象,但是依赖的表在SYSTEM用户下。这次迁移impdp指定的schema=LC,没有包含索引所依赖的表,判断大概率因为没有表所以索引也就没有导入。又产生了新的问题,既然没有表,那为什么导入的时候没有报错呢?下面通过实验验证
代码语言:javascript复制SQL> conn test/test
Connected.
SQL>
SQL>
SQL> create table t2(c1 number);
Table created.
SQL> insert into t2 values(98888888);
1 row created.
SQL> commit ;
Commit complete.
SQL> grant select,index on t2 to scott;
Grant succeeded.
SQL> conn scott/tiger
Connected.
SQL> create index i_2 on test.t2(c1);
Index created.
SQL>
SQL> exit
[oracle@leadx ~]$ expdp '/ as sysdba ' directory=data_pump_dir schemas=scott dumpfile=exp1.dmp
Export: Release 11.2.0.4.0 - Production on Tue Mar 9 23:51:35 2021
Copyright (c) 1982, 2011, Oracle and/or its affiliates. All rights reserved.
Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
Starting "SYS"."SYS_EXPORT_SCHEMA_01": "/******** AS SYSDBA" directory=data_pump_dir schemas=scott dumpfile=exp1.dmp
Estimate in progress using BLOCKS method...
Total estimation using BLOCKS method: 0 KB
Processing object type SCHEMA_EXPORT/USER
Processing object type SCHEMA_EXPORT/SYSTEM_GRANT
Processing object type SCHEMA_EXPORT/ROLE_GRANT
Processing object type SCHEMA_EXPORT/DEFAULT_ROLE
Processing object type SCHEMA_EXPORT/PRE_SCHEMA/PROCACT_SCHEMA
Master table "SYS"."SYS_EXPORT_SCHEMA_01" successfully loaded/unloaded
******************************************************************************
实验结论:表在LC用户下,索引在SYSTEM用户下,使用数据泵导出指定schema=LC,则并不会将A用户下的对应索引导出,所以导入的时候也就不会报错。 索引是属于表的,表是system下的,导出的是lc用户,就不会导出那个索引,索引不能单独存在。
最后咨询业务开发方,这几个表非业务表,忽略即可。
3.ORA-31679 表中含有long类型的列处理
ORA-31679: Table data object “LC”.“XXXXXXXXIN_229X68” has long columns, and longs can not be loaded/unloaded using a network link
意思就是含有long类型列的表,不能通过network_link方式直接导入。 查询官方文档:DataPump Import Of Tables Containing LONG Columns Using NETWORK_LINK Raises The Error ORA-31679 (Doc ID 1470331.1)
解决办法:
- 按照mos说的,单独导出这个表为dmp文件,再单独导入一次;
--源库
expdp "/ as sysdba" directory=dmp_dir dumpfile=single_table.dmp logfile=single_table.log tables=LC.XXXXXXX_229568;
--目标库
impdp "/ as sysdba" directory=dmp_dir dumpfile=single_table.dmp logfile=imp_single.log tables=LC.XXXXXXX_229568 remap_schema=LC:LC;
按照上述操作后,可在目标库正常查询数据
- 网上查到的有说可以用exp/imp;
4. ORA-31693、ORA-01400
ORA-31693: Table data object “LC”.“XXXXXXXXXH_201X0808” failed to load/unload and is being skipped due to error: ORA-01400: cannot insert NULL into (“LC”.“XXXXXXXXXH_201X0808”.“BASE_TYPE”)
查了一下"XXXXXXXXXH_201X0808"表的"BASE_TYPE"列约束为not null,查询该列内容确实有为“空”的情况,但是很奇怪条件语句用 is null 或者是=’ '又搜不出,跟客户确认过为备份表可忽略后没在继续确认(这个习惯不好,遇到问题应该查到底)
5.若干compilation warnings(编译警告)
代码语言:javascript复制ORA-39082: Object type ALTER_FUNCTION:"LC"."SXXXT" created with compilation warnings
ORA-39082: Object type VIEW:"LC"."WH_XXXXXXXXXXTORY" created with compilation warnings
ORA-39082: Object type TRIGGER:"LC"."GXXXXXXXXXESS_SEQ" created with compilation warnings
编译告警一般是这些对象在源库就已经是INVALID状态了,可以到dba_objects视图确认下
一般迁移完成需要重新编译,执行下方编译脚本:
代码语言:javascript复制@?/rdbms/admin/utlrp
6.ORA-04052、ORA-00604、ORA-02019
代码语言:javascript复制ORA-04052: error occurred when looking up remote object RESECH.VI_SCXXXXXLECT@EM
ORA-00604: error occurred at recursive SQL level 3
ORA-02019: connection description for remote database not found
明显是找不到远程对象,查询源库的dba_db_links表并没有发现名为EM的dblink,忽略
7.总结
对这篇的补充 https://www.modb.pro/db/38130