在Oracle数据库中,在导出含LOB字段的大表时(尤其是当 表未分区,并且表大小已过TB),在导出过程中经常遇到因undo表空间大小和undo_retention设置保留时间,导致ORA-01555: snapshot too old的报错。那该怎么避免呢?
通过rowid或者主键的方式分批导出(推荐使用rowid),可以巧妙的解决类似的问题:
--创建一个表用于记录要导出表的rowid,并分批,这里分成50
create table scott.exp_rowid as select mod(rownum,50) sou_seq,rowid sou_rowid from scott.lobtest;
示范参数文件:
--根据分批次数生成对应的parfile文件
cat >expdp_lobtest_seq0.par <
userid='/ as sysdba'
directory=datadump
dumpfile=expdp_lobtest_%U.dmp
logfile=expdp_lobtest.log
cluster=no
tables=scott.lobtest
query="where rowid in (select sou_rowid from scott.exp_rowid where sou_seq=0)"
EOF
执行:
--执行导出
nohup expdp expdp_lobtest_20181219_seq0.par > expdp_lobtest_seq0.par.out &
…..
nohup expdp expdp_lobtest_20181219_seq50.par > expdp_lobtest__seq50.par.out &
分成50个批次导出,可通过循环生成导出脚本
或者通过如下脚本:
chunk=10
for ((i=0;i<=9;i++));
do
expdp /as sysdba TABLES=LOBTEST QUERY=LOBTEST:\"where mod\(dbms_rowid.rowid_block_number\(rowid\)\, ${chunk}\) = ${i}\" directory=DMP dumpfile=lobtest_${i}.dmp logfile= lobtest_${i}.log &
echo $i
done
类似的方法,在实践中是非常有效的。