暂无图片
暂无图片
4
暂无图片
暂无图片
暂无图片

Oracle 11g到19c迁移TB级lob表的酸爽

IT那活儿 2020-07-22
3420

从Oracle数据库官方服务支持生命周期表我们可以清晰看到Oracle11g已过主支持生命周期,2020年后不再支持,取而代之的是12C及以上版本。


基于这个背景,大部分的客户开始了新一轮的数据库升级,下文主要剖析一个和升级相关的Case,希望对大家有帮助。


某客户系统基于版本迭代要求,需要将某核心数据库Oracle11.2.0.3升级至Oracle19.5版本,该系统业务数2.5TB,对于运营商系统来说,这体量的数据量是小儿科,凭借老司机的第一感觉割接应该没啥问题。


但是查看后发现有个单表2TB,仔细再查2TB基本全是lob,且不是分区表,这个问题就有点棘手了。搞的小哥我有点出汗的感脚了。


针对这种大容量的lob表,使用以往常规导出的方式,毫无悬念的报Ora-01555。


作为身经百战的割接小王子,见到挑战我就兴奋,接着出汗。经过自我风暴后,决定用Expdp的Query试一试,但是2TB的数据量的单表lob还是第一次,那么根据哪个条件进行Query导出呢?


首先需考虑到是根据有索引列进行导出,这样的效率会比较高。确认后,问题又来了,索引列不满足均匀分批条件,故这个思路走不通了。


要怎样才能均分呢,继续自我风暴中,要均分,Rowid行不行?Oracle提供了rowid这个概念。那就来看看怎么使用rowid进行导出的。


首先Rowid是用于定位数据库中一条记录的一个相对唯一地址值。通常情况下,该值在该行数据插入到数据库表时即被确定且唯一。Rowid它是一个伪列,它并不实际存在于实体表中。


它是Oracle在读取表中数据行时,根据每一行数据的物理地址信息编码而成的一个伪列。所以根据一行数据的Rowid能找到一行数据的物理地址信息。从而快速地定位到数据行,而且使用Rowid来进行单记录定位速度是最快的。


上图是Rowid的结构图,主要包含4个部分:

  • 第一部分6位表示:该行数据所在的数据对象的Data_object_id

  • 第二部分3位表示:该行数据所在的相对数据文件的id

  • 第三部分6位表示:该数据行所在的数据块的编号

  • 第四部分3位表示:该行数据的行的编号


虽然我们从Rowid伪列中Select出来的Rowid是以base64字符显示的,但在Oracle内部存储的时候还是以原值的二进制表示的。


一个扩展Rowid采用10个byte来存储,共80bit,其中obj#32bit,rfile#10bit,block#22bit,row#16bit。所以相对文件号不能超过1023,也就是一个表空间的数据文件不能超过1023个(不存在文件号为0的文件),一个Datafile只能有2^22=4M个 block,一个block中不能超过2^16=64K行数据的由来。


了解了Rowid后,怎么进行均匀分批呢?答案是利用Oracle提供的DBMS_ROWID 包。


导出脚本如下:



参数说明:

Content=DATA_ONLY

只导出表中的数据,导出会更快,导入时也更快,index之类的对象在data导入后单独处理;


COMPRESSION=DATA_ONLY

数据量太大,节省空间,传输到新环境时效更高


Query=“……”


将表数据根据条件进行分批,在一个scn内导出全部数据

为啥选用rowid_block_number呢?因为导出这个大表的需求下,Object_id就一个,分不了批次,Fileid只有150个,BLOCK_ID 是126924个,ROW_NUMBER是19,数据量数值进行Mod取余分批的差异就越小,所以使用rowid_block_number。使用这个方法后还是很顺利的导出了数据。


查看全部导出日志,每个批次耗时相差不大,满足均匀分批导出的计划。


总结,遇到超大lob表导数需求后的三板斧:


A.查看是否是分区表,分区表的话按分区导出;


catexp_owner_table_seq.par

userid='/assysdba'

directory=DMP

dumpfile=exp_owner_table_seq.dmp

logfile=exp_owner_table_seq.log

CONTENT=DATA_ONLY

COMPRESSION=DATA_ONLY

tables=(

onwer.tbale_name:part_name

)


B.业务沟通,是否存在均匀分布的字段值,按照字段值分批导出;


catexp_owner_table_seq.par

USERID='/as sysdba'

directory= DMP

CONTENT=DATA_ONLY

COMPRESSION=DATA_ONLY

dumpfile=exp_owner_table_seq.dmp

logfile=exp_owner_table_seq.log

tables=owner.table_name

QUERY="WHEREcolumn_name like 'XXXX%'


C.不满足以上的都可以使用本文rowid方式进行导出。


catexp_owner_table_seq.par

USERID='/as sysdba'

directory= DMP

CONTENT=DATA_ONLY

COMPRESSION=DATA_ONLY

dumpfile=exp_owner_table_seq.dmp

logfile=exp_owner_table_seq.log

tables=owner.table_name

QUERY="wheremod(dbms_rowid.rowid_block_number(rowid),10)=1"


以上是本小王子实际工作中遇到的2TB数据量lob的处理过程,希望对大家有启发借鉴的作用和意义,后续割接迁移中遇到好玩儿的事情,我再来和大家分享。我们后会有期。

最后修改时间:2020-07-22 11:05:39
文章转载自IT那活儿,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论