生产环境中如何对大对象进行分片expdp\impdp?

1、介绍

在做迁移、搭建测试库以及其他需要导出、导入数据的需求下,我们常用到数据泵来进行数据的转移操作,但往往很多事后我们要操作的库数据量都非常大,且数据库中大对象字段非常多,就给我们导出带来了一些问题,如报错ora-01555,导出慢或者卡在那里很久不动等问题;

有小伙伴可能会说你开并行不就行了吗?事实上当你数据库中大对象数据量占用较大时候,你会发现开并行没有任何用,那么怎么解决这个问题呢?我的思路是先排除大对象的表;然后再通过rowid切片多个进程导出导入。

下面是一个示例:

--查看大对象,先排除导出,然后再单独导出SELECT owner,tablespace_name,case SEGMENT_type         when 'LOBSEGMENT' then          (select table_name || '.' || column_name             from dba_lobs t            where t.segment_name = s.segment_name)         else          SEGMENT_NAME       end as SEGMENT_NAME,       BYTES / 1024 / 1024 MB,       BYTES / 1024 / 1024 / 1024 GB  FROM DBA_SEGMENTS s --WHERE TABLESPACE_NAME = upper('ZL_ZLEMR') Order By 4 Desc,3 asc;
 --通过查询发现 【 检验报告图像.图形 】这个字段占用了400g的空间,我需要先进行排除

2、第一步导出主体数据:

--排除系统用户select username,account_status,lock_date,default_tablespace,created from dba_users order by created;--创建数据泵目录create directory dump as 'E:\dump\';grant read,write on directory dump to system;exit;--生成符合expdp的排除用户的脚本declare s1 varchar2(2000);cursor c is select username from dba_users where trunc(created) =to_date('2013/10/9','yyyy/mm/dd'); begin  for j in c loop    s1 :=s1||'\'||''''||j.username||'\'||''''||',';    --s1 :=s1||''''||j.username||''''||',';  end loop;  dbms_output.put_line(s1);end;--将上面的脚本复制进来expdp \"/ as sysdba \" dumpfile=his.dmp logfile=his.log directory=dump full=y EXCLUDE=audit,TABLE:\"IN\(\'检验报告图像\'\)\" EXCLUDE=SCHEMA:\"in\(\'SYSTEM\',\'SYS\',\'OLAPSYS\',\'SI_INFORMTN_SCHEMA\',\'MGMT_VIEW\',\'ORDPLUGINS\',\'ORACLE_OCM\',\'XDB\',\'SYSMAN\',\'WMSYS\',\'SCOTT\',\'DBSNMP\',\'DMSYS\',\'DIP\',\'OUTLN\',\'EXFSYS\',\'ANONYMOUS\',\'CTXSYS\',\'ORDSYS\',\'MDSYS\',\'MDDATA\'\)\"

3、rowid切片导出数据的原理是什么?

我们先来看rowid是怎么切片的,才知道具体我们应该如何来控制并行;
SQL> select distinct mod(dbms_rowid.rowid_block_number(rowid),10) from zlhis.检验报告图像 a order by 1;
MOD(DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID),10)--------------------------------------------                                           0                                           1                                           2                                           3                                           4                                           5                                           6                                           7                                           8                                           9
已选择 10 行。
SQL> select  mod(dbms_rowid.rowid_block_number(rowid),3),count(*) from zlhis.检验报告图像 a group by mod(dbms_rowid.rowid_block_number(rowid),3);
MOD(DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID),3)   COUNT(*)------------------------------------------- ----------                                          1       2983                                          2       2936                                          0       2920
--通过上面结果我们可以看到,rowid分配就是通过mod(v1,v2)来进行的,其中v2参数就是控制并行的参数值,可以理解为数据泵你parallel=v2
                                          

4、正式导出

在本步骤中我改写了网上的一些发的脚本,因为在实际实验过程中和生产中我发现他们都存在一些问题,比如数据泵还没开始产生进程下一个就开始了,导致一些报错和数据没导出的情况;

1)linux#!/bin/bashchunk=9for ((i=0;i<=8;i++));doexpdp zlhis/9d22bbb TABLES=检验图像结果 QUERY=检验图像结果:\"where mod\(dbms_rowid.rowid_block_number\(rowid\)\, ${chunk}\) = ${i}\" directory=DMP dumpfile=TX_${i}.DMP logfile=TX_${i}.log &echo $isleep 10done 
2)windows@echo off
set connStr=zlhis/9d22bbbset chunk=10set oracle_sid=orclset oracle_home_path=d:\oracle\product\10.2.0\db_1\bin\
rem 格式:FOR /L %variable IN (start,step,end) DO command [command-parameters]
for /l %%a in (0,1,9) do (start /b %oracle_home_path%expdp %connStr% TABLES=检验图像结果 QUERY=检验图像结果:\"where mod\(dbms_rowid.rowid_block_number\(rowid\)\,%chunk%\) = %%a\" directory=expdpdump dumpfile=TX_%%a.DMP logfile=TX_%%a.logtimeout 10 >nul 2>nul)

3)手工方式---或者手动导出--如下,打开三个窗口分别粘贴执行,如果要开更多的进程,需要更改3后后面的0~2SQL> create or replace directory dmp as 'D:\dump\';SQL> grant read,write on directory dmp to public;
expdp zldoc/zlsoft tables=BZ_DOC_LOG  QUERY=BZ_DOC_LOG:\"where mod\(dbms_rowid.rowid_block_number\(rowid\)\,3\) = 0\" directory=DMP dumpfile=bz_doc_log_0.dmp logfile=bz_doc_log_0.logexpdp zldoc/zlsoft tables=BZ_DOC_LOG  QUERY=BZ_DOC_LOG:\"where mod\(dbms_rowid.rowid_block_number\(rowid\)\,3\) = 1\" directory=DMP dumpfile=bz_doc_log_1.dmp logfile=bz_doc_log_1.logexpdp zldoc/zlsoft tables=BZ_DOC_LOG  QUERY=BZ_DOC_LOG:\"where mod\(dbms_rowid.rowid_block_number\(rowid\)\,3\) = 2\" directory=DMP dumpfile=bz_doc_log_2.dmp logfile=bz_doc_log_2.log

5、正式导入

1)linux--脚本导入#!/bin/bashfor ((i=0;i<=8;i++));do#echo dumpfile=TX_${i}.DMPimpdp \"/ as sysdba\" directory=impdpdump dumpfile=TX_${i}.DMP logfile=impdp_TX_${i}.log DATA_OPTIONS=DISABLE_APPEND_HINT TRANSFORM=DISABLE_ARCHIVE_LOGGING:Y CONTENT=DATA_ONLY &sleep 10done
2)windows@echo off
set connStr=zlhis/9d22bbbset oracle_sid=orclset oracle_home_path=d:\oracle\product\10.2.0\db_1\bin\
rem 格式:FOR /L %variable IN (start,step,end) DO command [command-parameters]
for /l %%a in (0,1,9) do (rem 11g upper >start /b %oracle_home_path%impdp %connStr% directory=impdpdump dumpfile=TX_%%a.DMP logfile=imp_TX_%%a.log DATA_OPTIONS=DISABLE_APPEND_HINT TRANSFORM=DISABLE_ARCHIVE_LOGGING:Y CONTENT=DATA_ONLY
start /b %oracle_home_path%impdp %connStr% directory=impdpdump dumpfile=TX_%%a.DMP logfile=imp_TX_%%a.log CONTENT=DATA_ONLYtimeout 10 >nul 2>nul)


3)手工方式---或者手动导入,更安全truncate table zldoc.bz_doc_log;impdp \"/ as sysdba\" directory=dmp dumpfile=bz_doc_log_0.dmp DATA_OPTIONS=DISABLE_APPEND_HINT CONTENT=DATA_ONLYimpdp \"/ as sysdba\" directory=dmp dumpfile=bz_doc_log_1.dmp DATA_OPTIONS=DISABLE_APPEND_HINT CONTENT=DATA_ONLYimpdp \"/ as sysdba\" directory=dmp dumpfile=bz_doc_log_2.dmp DATA_OPTIONS=DISABLE_APPEND_HINT CONTENT=DATA_ONLY

6、那么我们导出过程中如果遇到了业务卡顿或者我想停止怎么办呢?

select s.inst_id,to_char(sysdate,'YYYY-MM-DD HH24:MI:SS') "DATE", s.program, s.sid, 'orakill orcl2 '||spid,'kill -9 '||spid,         s.status, s.username, d.job_name, p.spid, s.serial#, p.pid ,'ALTER SYSTEM KILL SESSION '||''''||s.SID||','||s.SERIAL#||',@'||s.inst_id||''''||' IMMEDIATE;' killse  from gv$session s, gv$process p, dba_datapump_sessions d   where p.addr=s.paddr and s.saddr=d.saddr and s.inst_id=p.inst_id and s.inst_id=d.inst_id; 
select 'orakill orcl '||spid ,'ALTER SYSTEM KILL SESSION '||''''||t1.SID||','||t1.SERIAL#||''''||' IMMEDIATE;' killse--,'kill -9 '||spid                from sys.gV_$PROCESS t,gv$session t1,dba_datapump_sessions d                 where t.addr=t1.paddr and t1.saddr=d.saddr                and t1.Type='USER' and t1.username is not null;
select 'drop table ' || owner_name || '.' || job_name || ' purge;'  from dba_datapump_jobs where state = 'NOT RUNNING' ;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值