暂无图片
暂无图片
暂无图片
暂无图片
1
暂无图片

Oracle关于大字段对象表的迁移(数据泵)

炬南山 2020-04-16
1509



Oracle关于大字段对象表的迁移(数据泵)



我们在数据库日常运维过程中,经常会使用数据泵(expdp\impdp)对数据库做导出导入操作,从而实现数据库的部分或全量数据迁移(如搭建测试库、迁移生产库、合并数据库等)。

然而在数据的导出导入过程中,我们会发现比较大的大字段表会很影响整个导出导入效率,甚至无法正常完成。普通表我们可以采取加并行参数(parallel)来提升导出导入效率,但此参数针对于大字段表是无效的,即使加了并行参数,大字段表还是单进程执行导出导入操作。




背 景

有套业务子库(大小大概2T)需要迁移合并至其业务主库,由于是合并操作,在排除使用ADG、XTTS、OGG等迁移方案之后,考虑采用数据泵导出导入的方式进行合并迁移。整个合并迁移时间(包括数据库迁移合并+业务测试)限制在7小时以内,数据库中大部分表通过并发导出导入等优化方式可以在5小时内完成,唯独有一张包含200多G大字段对象的表仅仅是导出花费十几个小时也未完成,直至报错(报快照过久)。通过扩展undo表空间及调整参数undo_retention,最终还是导出失败。


分析原因

LOB字段的表导出时即使加并行参数也是无效的,还是单进程在导出表数据,表本身包含220G数据,大字段数据就占202G,数据量比较大,加上源端服务器是普通的X86服务器,数据在导出过程中还会发生变化,最终由于耗时过久,导出失败。

解决问题

数据库总共有2T数据,其他1.8T数据通过开并行等手段基本可以在2小时之内导出完成,唯独此大字段表即使导出十几个小时也无法正常完成,所以首先我们要尝试解决并行的问题,通过一定的手段使大字段表的导出能够并发进行。

既然并行参数parallel对大字段表是无效的,在不改变表结构及数据的情况下,我们可以尝试将表从逻辑上拆分成一个一个的小单位,每个小单位拉起一个导出进程,这样就可实现大字段表的并行导出操作。

那如何逻辑拆分大字段表呢?如果表上有日期字段,我们可以按日期字段拆分表,再如表上有区域字段,我们也可以按区域字段做拆分,即使没有特别明显的可以区分数据的字段,我们也可以按rowid去做拆分。

其实按rowid去做拆分是一个很好的方式,因为oracle做数据插入时是无序插入的(同一时刻多个进程对同一张表做插入,数据可能存放在不同的数据块上,并不是一个数据块使用完之后,再插入新的数据块),但了解oracle存储结构的会知道,如果我们不管数据的组成,rowid(rowid是由对象编号+文件号+数据块编号+行号组成)其实是有序的,我们如果按rowid有序的去做拆分,就可以尽量少读数据块(相较于索引扫描及全表扫),从而提升整个导出效率。


准备工作

首先我们创建一张中间表,将表数据的rowid按顺序记录下来(全表扫有序读取相邻的数据块),方便之后做拆分

create table t_test_split as select *+parallel(4)*/rowid sou_rowid,rownum rn,(select current_scn from v$database) scn from t_test;

注:虽然合并迁移过程中业务子库是停业务不再读写的,但为了保证数据的一致性,我们还是选择把数据库的scn号记录下来。例如在数据库不停机的情况下,你在搭建OGG环境初始化大字段表时,这里保存的scn号就非常有用了。

正式执行导出导入

源库拉起导出主进程,通过rowid将表拆分成一个一个的小单元,每个小单元拉起一个独立子进程单独导出一部分表数据,子进程导出完成生成一个标记文件用来标记子进程已导出完成。目标库拉起导入的主进程,监控导出的标记文件,一旦发现导出完成的子进程标记文件就开始执行导入,一直到源库小单元全部导出完成为止。

注:由于案例中的环境在源库和目标库之间设置了nfs共享目录,所以无需scp网络传输导出的数据文件及标记文件。

1
导出-初始化环境变量
我们用shell来实现大字段表并发导出,首先配置好相关的环境变量,初始化一些实用方法
2
导出-编写导出用的主shell脚本
我们编写拆分并导出大字段表的主体shell脚本

#这里必须要创建一个子shell,不然无法实现并发导数,如果不创建子shell,直接在主进程拉起导数,则主shell进程需要等待当前发起的导数命令完成才会继续往下执行从而循环发起其他导数进程

生成的导数文件如下图:



3

导出-编写导出用的子shell

编写拆分并导出大字段表的子shell脚本


4
导出-正式导出

nohup sh expdp_lob_tab.sh>expdp_lob_tab.sh.out &


5
导入-初始化环境变量
同样的,我们配置导入相关的环境变量,初始化一些实用方法


6
导入-编写导入用的主shell脚本

我们编写导入大字段表的主体shell脚本,和导出主shell基本类似


7
导入-编写导入用的子shell

编写导入大字段表的子shell脚本


8
导入-正式导入

nohup sh impdp_big_tab.sh>impdp_big_tab.sh.out &

导入完成结果如下图:


成 效

原本十几个小时(可能不只这么久,因为十几个小时之后导出报错)无法导出的大字段表,最终两个多小时就导出完成。加上导入时间最终可将整个导出导入时间控制在5小时以内,满足迁移合并时间要求。

总 结

我们在对大字段表用数据泵做导出导入时,由于并行参数对其无效,如果发现导出导入效率无法满足要求,可尝试人工将表逻辑拆分成小单元,每个小单元独立导出一部分数据,以此来提升导出导入效率。



[  里昂.成  ]

作者简介:
资深数据库工程师,会开发、懂运维、善优化。拥有十几年程序开发、数据库运维经验,擅长oracle、mysql数据库调优及SQL调优
文章转载自炬南山,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论

www
暂无图片
1年前
评论
暂无图片 0
点赞
1年前
暂无图片 点赞
评论