如今已经是Oracle Database 21c的时代了,你是否还考虑过使用EXP/IMIP这些9i中的工具呢?

其实在特殊的场景中,这些看似“老的工具”,也是可以帮助你解决棘手的问题。

比如:可以在数据库只读模式下,导出数据等。又或者将其应用在我下文中所描述的场景中。

进入正题,某客户找到我,描述了其数据库无法启动的故障,经过分析得出数据库软件被注入了恶意的代码,导致TAB$表数据被删除,从而无法启动数据库,告警日志里面的输出如下:

Errors in file D:\APP\ADMINISTRATOR\diag\rdbms\xxxx\xxxx\trace\xxxx_ora_13308.trc  (incident=26578):
ORA-00600: 内部错误代码, 参数: [16703], [1403], [20], [], [], [], [], [], [], [], [], []
Incident details in: D:\APP\ADMINISTRATOR\diag\rdbms\xxxx\xxxx\incident\incdir_26578\xxxx_ora_13308_i26578.trc
Use ADRCI or Support Workbench to package the incident.
See Note 411.1 at My Oracle Support for error and packaging details.
Errors in file D:\APP\ADMINISTRATOR\diag\rdbms\xxxx\xxxx\trace\xxxx_ora_13308.trc:
ORA-00704: 引导程序进程失败
ORA-00704: 引导程序进程失败
ORA-00600: 内部错误代码, 参数: [16703], [1403], [20], [], [], [], [], [], [], [], [], []
Errors in file D:\APP\ADMINISTRATOR\diag\rdbms\xxxx\xxxx\trace\xxxx_ora_13308.trc:
ORA-00704: 引导程序进程失败
ORA-00704: 引导程序进程失败
ORA-00600: 内部错误代码, 参数: [16703], [1403], [20], [], [], [], [], [], [], [], [], []
Error 704 happened during db open, shutting down database
USER (ospid: 13308): terminating the instance due to error 704

这种攻击事件,网上有很多讨论,有机会再给大家详细分析这个故障。此篇文章主要记录一下,在处理这个恶意攻击过程中,为了导出数据到新搭建的数据库中,所遇到一些EXP和IMP的技术点。

首先,由于无法完美恢复数据块,于是选择使用传输表空间技术,将被破坏数据库的数据迁移到新搭建的数据库里。但由于数据字典有问题,使用EXPDP导出元数据信息时,会报错误,无法进行。这个时候,只有选择用EXP工具来进行导出元数据工作。

使用传输表空间完成后,一些没有段的对象,如view,sequence,function等等是没有办法一起导入的,因为这些对象的定义信息都放在SYSTEM表空间里。因此,我们再次使用EXP和IMP,对schemas数据进行导出和导入,步骤如下:

1. 传输表空间导出元数据:

exp '/ as sysdba' file=sandata_exp.dmp log=sandata_exp.log transport_tablespace=y tablespaces=SANDATA_IDX,SANDATA statistics=none

使用statistics=none选项可以避免下面描述的EXP-00091的报错。

EXP-00091: 正在导出有问题的统计信息。

如果数据库的字符集和操作系统的不一致,会有如下报错:

连接到: Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
已导出 ZHS16GBK 字符集和 AL16UTF16 NCHAR 字符集
服务器使用 AL32UTF8 字符集 (可能的字符集转换)
注: 将不导出表数据 (行)
即将导出可传输的表空间元数据...

2. 导入表空间到新数据库中,由于文件比较多,因此使用parfile文件来执行。这是因为一条命令如果过长的话,是无法正常执行的。

imp '/  as sysdba' parfile='sandata.txt'

parfile文件sandata.txt的内容:

TRANSPORT_TABLESPACE=y
datafiles='D:\APP\ADMINISTRATOR\ORADATA\SANDATA\SANDATA01.DBF'
datafiles='D:\APP\ADMINISTRATOR\ORADATA\SANDATA\SANDATA02.DBF'
datafiles='D:\APP\ADMINISTRATOR\ORADATA\SANDATA\SANDATA03.DBF'
datafiles='D:\APP\ADMINISTRATOR\ORADATA\SANDATA\SANDATA04.DBF'
datafiles='D:\APP\ADMINISTRATOR\ORADATA\SANDATA\SANDATA05.DBF'
datafiles='D:\APP\ADMINISTRATOR\ORADATA\SANDATA\SANDATA06.DBF'
datafiles='D:\APP\ADMINISTRATOR\ORADATA\SANDATA\SANDATA07.DBF'
datafiles='D:\APP\ADMINISTRATOR\ORADATA\SANDATA\SANDATA08.DBF'
datafiles='D:\APP\ADMINISTRATOR\ORADATA\SANDATA\SANDATA09.DBF'
datafiles='D:\APP\ADMINISTRATOR\ORADATA\SANDATA\SANDATA010.DBF'
datafiles='D:\APP\ADMINISTRATOR\ORADATA\SANDATA\SANDATA011.DBF'
datafiles='D:\APP\ADMINISTRATOR\ORADATA\SANDATA\SANDATA012.DBF'
datafiles='D:\APP\ADMINISTRATOR\ORADATA\SANDATA\SANDATA_IDX_01.DBF'
tablespaces=SANDATA,SANDATA_IDX
file=sandata_exp.dmp
log=sandata_tts.log

3.完成后,view,sequence,function等没有导入,于是我们再次按照用户导出这些内容;

   其中最重要的选项就是rows=n,此选项表示不导出表的任何数据;也可以按需选择indexes=n,constraints=n,triggers=n等选项。

   这样我们就获得了view,sequence,function等内容,同时又没有导出数据了。

exp '/ as sysdba' file=sandata_schemas.dmp log=sandata_schemas.log owner=sandata rows=n indexes=n constraints=n triggers=n

4.导入到新数据库中,此时ignore=y和rows=n选项都要使用上。

imp '/  as sysdba' file=sandata_schemas.dmp log=sandata_imp_schemas.log fromuser=sandata touser=sandata ignore=y rows=n

如果源数据库和目标数据库字符集不一样,在导入时会报如下错误:

Export file created by EXPORT:V11.02.01 via conventional path
About to import transportable tablespace(s) metadata...
import done in ZHS16GBK character set and AL16UTF16 NCHAR character set
. importing SYS's objects into SYS
. importing SYS's objects into SYS
IMP-00017: following statement failed with ORACLE error 29345:
 "BEGIN   sys.dbms_plugts.beginImport ('11.2.0.4.0',873,'2000',12,'Microsoft "
 "Windows x86 64-bit',96170,7289301,2,1,1,0); END;"
IMP-00003: ORACLE error 29345 encountered
ORA-29345: cannot plug a tablespace into a database using an incompatible character set
ORA-06512: at "SYS.DBMS_PLUGTS", line 2610
ORA-06512: at "SYS.DBMS_PLUGTS", line 2119
ORA-06512: at line 1
IMP-00000: Import terminated unsuccessfully

5.不要忘了最后核对一下源库和目标库中对象的数量是否一致。

总结,EXP工具不如EXPDP功能丰富,当遇到不得不用EXP工具时,可以参考本文章。正所谓,工具没有老和旧,只有适用和不适用。