数据泵是Oracle 10g及以上版本所提供的数据库逻辑备份恢复工具,其因为具有高效、稳定、快速的特点,得到了广大DBA的青睐,Oracle官方也明确建议使用数据泵来替代原来的EXP(导出)和IMP(导入)。
EXP作为普通客户端进程,主要通过连接数据库来获取需要备份的数据,并写入客户端本地。而EXPDP则是启动数据库服务器端的进程,主要通过服务器进程来完成数据的备份,并将备份文件写入数据库服务器端,使备份变得更为高效。
相比于EXP和IMP,数据泵有什么优势呢,二者的区别又有哪些呢?
·数据泵必须使用特定的数据库目录对象DIRECTORY,而不是像EXP那样只需要在命令行中指定路径即可。
·数据泵可以评估导出对象的大小。
·数据泵可以通过DBLINK将远端的数据库直接导入当前的数据库环境中,使测试与迁移变得更方便快捷。
·数据库需要处于读写模式下,因为数据泵在运行过程中,会临时创建一张表格,用于记录数据泵运行的相关信息。也正是因为该表格的创建,数据泵可以进行断点记录,从而使操作变得更为灵活。
·数据泵具有更多的筛选条件,可以有选择性地导出部分数据。
在日常工作中,数据泵的使用需要注意以下几点。
1)在非DBLINK方式导入的情况下,需要确保服务器端数据泵导出目录有足够的空间。
要想预估导出文件的大小,可以使用“ESTIMATE_ONLY=Y”选项运行EXPDP。例如,预估导出SCOTT用户所需空间的大小,命令如下:
shell> expdp \'/ as sysdba\' schemas=scott ESTIMATE_ONLY=Y Starting "SYS"."SYS_EXPORT_SCHEMA_01": "/******** AS SYSDBA" schemas=scott estimate_only=y Estimate in progress using BLOCKS method... Processing object type SCHEMA_EXPORT/TABLE/TABLE_DATA . estimated "SCOTT"."DEPT" 64 KB . estimated "SCOTT"."EMP" 64 KB . estimated "SCOTT"."SALGRADE" 64 KB . estimated "SCOTT"."BONUS" 0 KB Total estimation using BLOCKS method: 192 KB Job "SYS"."SYS_EXPORT_SCHEMA_01" successfully completed at Mon Jan 27 20:29:44 2020 elapsed 0 00:00:03
2)确定expdp/impdp两个数据库之间的字符集是否兼容。对于不兼容的处理方式,本章案例部分会展开。
3)数据字典统计信息应确保准确。数据泵的性能依赖于数据库字典统计信息的准确性,若长时间未收集统计信息,则会严重影响数据泵的性能,建议使用以下语句收集统计信息。
统计数据字典基表(物理存在的基表)的命令如下:
shell> exec dbms_stats.gather_dictionary_stats();
统计基表动态表格的命令如下:
shell> exec dbms_stats.gather_fixed_objects_stats();
4)低版本向上兼容,而高版本导入低版本需要注意是否正常。
5)导入Oracle 12c及以上版本时,建议搭配“TRANSFORM=DISABLE_ARCHIVE_LOGGING:Y”参数,在归档模式下不生成归档日志。
Oracle的功能非常强大,其提供的命令成千上万,我们不可能全部记住。笔者认为在使用Oracle时,只需要知道如何查询这些命令即可,对于数据泵,建议大家记住“expdp/impdp -help”命令。其中几个关键的参数用法如下。
·CLUSTER:RAC中默认为Y,利用集群资源并行工作,建议关闭(CLUSTER=N)。
·CONTENT:导出内容,默认为ALL,可以选择元数据[METADATA_ONLY]或仅数据[DATA_ONLY]。
·INCLUDE:导出/导入时指定的对象。
·EXCLUDE:与INCLUDE互斥,导出/导入时排除的对象。
·NETWORK_LINK:远端数据库DBLINK连接。
·PARFILE:参数文件,避免在不同的操作系统下,因转义字符的不同而带来影响。
·QUERY:特定对象筛选条件,类似于select中的where条件。
·SAMPLE:数据抽样比,一般用于搭建测试环境。
·SQLFILE:对导入内容生成SQL文本语句。
·REMAP_SCHEMA/REMAP_TABLE/REMAP_TABLESPACE:用于重定向目标端导入对象。
·COMPRESSION:导出文件压缩,空间紧张时可以使用此参数,可以选择所有内容[ALL]、元数据[METADATA_ONLY]或仅数据[DATA_ONLY]。
·PARTITION_OPTIONS:用于迁移分区表,NONE表示与源端保持一致,DEPARTITION表示将每个分区表和子分区表作为一个独立的表创建,并使用表和分区(子分区)名字的组合作为自己的名字,MERGE表示将所有分区合并到一个表。
1.Zhs16gbk导入UTF-8
UTF-8是Zhs16gbk的超集,后者的varchar2和char类型字段的存储长度是前者的1.5倍。因此我们只需要先导入表结构,修改字段的长度再导入数据即可。具体实现步骤如下。
1)导入目标端表结构,命令如下:
shell> impdp \'/ as sysdba\' DIRECTORY=expdir CONTENT=METADATA_ONLY DUMPFILE=scott_metadata.dmp logfile= scott_ metadata.log
2)修改表格中varchar2和char类型的字符长度,命令如下:
shell> select 'alter table ' || owner || '.' || table_name || ' modify (' || COLUMN_NAME || ' ' || DATA_TYPE || '(' || (case when DATA_LENGTH >= 2660 then 4000 else ceil(DATA_LENGTH * 1.5) end) || '));' from dba_tab_columns where table_name = 'DEPT' and DATA_TYPE in ('VARCHAR2', 'CHAR');
在目标端中执行上述生成的语句,以修改字段长度。
3)最后导入表格数据,命令如下:
shell> impdp \'/ as sysdba\' DIRECTORY=expdir CONTENT=DATA_ONLY DUMPFILE= scott_data.dmp logfile= scott_data.log
对于将全库GBK字符集迁移到UTF-8字符集,读者可以参考上述方法完成,此处不展开。
2.导出部分数据
对一个数据量在太字节(TB)级别的生产库做全库迁移费时又费力。但创建测试环境时,我们往往并不需要用到所有的数据,只需要使用部分数据进行功能性测试即可。对此,数据泵提供了两种方式用于导出部分数据,一种方式是QUERY,即按条件导出,类似于查询语句中的where。例如,导出业务用户下每张表格的前5000行数据,命令如下:
shell> expdp \'/ as sysdba\' parfile=expdp.par shell> cat expdp.par directory=EXPDIR parallel=4 CLUSTER=N dumpfile=his %U.dmp logfile=his.log schemas= ( 'HIS', 'MEDIA', 'APP', 'INPAUTO' ) query="where rownum<=5000"
另一种方式是SAMPLE,即数据抽样百分比。针对全库、用户和表三种模式,我们可以在导出时使用此参数来进行设置,使用方法示例如下。
导出SCOTT用户下每张表格20%的数据,命令如下:
shell> expdp \"/ as sysdba\" directory=EXPDIR dumpfile=scott_data.dmp logfile=scott_data.log schemas=scott sample=20
导出SCOTT用户下的所有表格,但只对大表emp抽取20%的数据,命令如下:
shell> expdp \"/ as sysdba\" directory=EXPDIR dumpfile=scott_data.dmp logfile=scott_data.log schemas=scott sample=scott.emp:20
针对特定表格进行采样处理,需要通过“数据表名:采样比例”的方式来指定。
3.使用SQLFILE获取源端信息
使用数据泵进行迁移时,我们需要在目标端提前创建好对应的表空间,那么对于源端损坏或无法查询信息的极端情况,又该如何处理呢?这时可以使用SQLFILE来解决此类问题。使用方法具体如下。
1)目标端导入可通过SQLFILE生成表空间创建语句,命令如下:
shell> impdp \"/ as sysdba\" directory=IMPDIR dumpfile=expdp_sqlfile.dmp full=y SQLFILE=expdp_sqlfile.sql
2)查看expdp_sqlfile.sql文件定位表空间创建语句,命令如下:
-- new object type path: DATABASE_EXPORT/TABLESPACE CREATE UNDO TABLESPACE "UNDOTBS1" DATAFILE SIZE 26214400 AUTOEXTEND ON NEXT 5242880 MAXSIZE 32767M BLOCKSIZE 8192 EXTENT MANAGEMENT LOCAL AUTOALLOCATE; ALTER DATABASE DATAFILE '/oracle/app/oracle/oradata/JASON11G/datafile/o1_mf_undotbs1_0au42s0g_.dbf' RESIZE 319815680; CREATE TEMPORARY TABLESPACE "TEMP" TEMPFILE SIZE 30408704 AUTOEXTEND ON NEXT 655360 MAXSIZE 32767M EXTENT MANAGEMENT LOCAL UNIFORM SIZE 1048576; CREATE TABLESPACE "USERS" DATAFILE SIZE 5242880 AUTOEXTEND ON NEXT 1310720 MAXSIZE 32767M, SIZE 10485760, '/oracle/app/oracle/oradata/JASON11G/datafile/user01.dbf' SIZE 104857600 LOGGING ONLINE PERMANENT BLOCKSIZE 8192 EXTENT MANAGEMENT LOCAL AUTOALLOCATE DEFAULT NOCOMPRESS SEGMENT SPACE MANAGEMENT AUTO; ALTER DATABASE DATAFILE '/oracle/app/oracle/oradata/JASON11G/datafile/o1_mf_users_0cu42s0l_.dbf' RESIZE 47185920;
expdp_sqlfile.sql包含了所有源端表空间信息,我们只需要修改相应的路径,在目标端执行即可,读者也可以根据SQLFILE的输出内容自定义修改。
4.对象重定向
我们在做多库整合时,往往需要将不同源端相同用户和表空间下的数据整合到同一个目标库的不同用户和表空间环境中。其中,REMAP_SCHEMA、REMAP_TABLE、REMAP_TABLESPACE起到了重定向的作用。
来看个示例,将源端tbs_jason表空间jason用户的表格导入目标端yh用户的tps_yh表空间中,命令如下:
shell> impdp \"/ as sysdba\" directory=IMPDIR dumpfile=expdp_jason.dmp remap_schema=jason:yh remap_tablespace=tps_jason:tps_yh
上述命令会将jason用户重定向为yh用户,tps_jason表空间重定向为tps_yh表空间。
目标端用户和表空间需要提前创建。
将源端分区表导入目标端普通表中的步骤具体如下。
1)源端导出。
2)目标端导入,使用SQLFILE预先生成建表语句,命令如下:
shell> impdp \"/ as sysdba\" directory=IMPDIR dumpfile=expdp_jason.dmp tables=tbs_ objects SQLFILE=tbs_objects.sql
获取SQLFILE语句,删除分区内容,并重命名为tbs_objects_bak,在目标端执行创建非分区表。
3)将源端分区表导入目标端非分区表中,命令如下:
shell> impdp \"/ as sysdba\" directory=IMPDIR dumpfile=expdp_jason.dmp tables= tbs_objects remap_tables= tbs_objects: tbs_objects_bak PARTITION_OPTIONS =merge