尉微 2017-11-11
我们有一套生产环境的Oracle数据库,虽然每天都有RMAN备份,但是也招架不住开发人员隔三差五就说要恢复几张表的前几天的数据到生产环境当中,针对这样的需求,用RMAN来恢复某几张表的数据就显的特别费劲了。于是我决定用Oracle数据库的逻辑备份工具EXPDP(数据泵导出)专门导出特定用户下的所有表的数据,并在每天凌晨4点通过LINUX操作系统的CRONTAB的计划任务定时执行来完成。这样,开发人员再有需要恢复某几张表的时候,直接用IMPDP(数据泵导入)工具导入某些表即可。这里,千万注意,导入时一定要加参数REMAP_TABLE,其目的在于给要导入的表起一个和原表容易区分的名字,避免覆盖原表的数据。建议命名方式为原表名_当前日期,这样可读性更强。见下图参数REMAP_TABLE使用说明:
上面是解决了能够满足开发人员要恢复某些表的问题,但这样的导出文件(*.DMP)每天生成的容量就很大,而且是存放在本地,可想而知,本地的存储空间容量有限,也不能一直保留每天生成的DMP文件,时间长了,服务器的磁盘存储空间会撑爆滴。于是,采用一种DMP文件的清除保留策略,即在本地仅保留一份当天的DMP数据泵导出文件,把当天的DMP文件通过SCP命令远程复制到另一台LINUX服务器(专门存放DMP文件,容量有50T,每块磁盘3.6T,共有14块磁盘),复制完以后,同时清除昨天的DMP文件,让本地服务器始终保留一份当天的DMP文件,这样本地服务器的磁盘空间容量的问题就迎刃而解了。
如果每天手工用SCP命令复制的话,至于查看复制了多少,什么时候复制完,也是一个不可控的环节。在这里把SCP命令的操作写到一个SHELL脚本里同时生成复制进度的日志文件,并每天定时执行这个SH脚本,不用人工去干预,这样效率就大大提高了。
由于远程服务器的磁盘空间也就那么多50T左右,其中每一块磁盘有3.6T,当第一块磁盘的空间不多的时候,比如把昨天的DMP文件复制到这块磁盘以后,它的可用空间已占93%,也就是剩余空间只有7%时,今天生成的DMP文件应该存放到第二块磁盘了。所以这种情况,应该在SH脚本中必须进行条件判断。也就是要查看当前使用磁盘的剩余空间还有多少G,以及当天生成的DMP文件总共有多少G,前者的容量应该大于后者的容量,才能将这些DMP文件保存在这块磁盘里。否则,说明该块磁盘空间不足,必须将DMP文件保存在下一块磁盘里。
当然,要读取远程服务器的当前保存DMP文件所在磁盘的剩余空间的容量,就要使用SSH连接远程服务器,如果本地服务器没有配置SSH信任远程服务器的功能,要SSH连接远程服务器时,需要输入远程服务器的密码才能连接,这就是所谓的服务器之间的交互现象。而在我们下面即将展现的SH脚本当中是不允许出现交互情形的,否则,就丧失了脚本的自动化功能。
为此,我们先配置本地服务器SSH信任远程服务器的功能,让本地服务器使用SSH命令能够直接连到远程服务器。操作步骤见下图所示:
上面箭头指示的3个地方,都直接回车即可。将本地服务器生成的SSH公钥文件内容复制到远程服务器时,报错了。
经过查询Google文档,发现是没有用参数-i指定本地服务器生成的SSH公钥文件,查看当前服务器的操作系统是RedHat Linux Server 5.4 x86_64。(而在CentOS 6.6 Server x86_64的操作系统上,直接就可以使用ssh-copy-id 远程主机名 而不报错)其中,查询Google的操作步骤见下图,
现在将本地服务器生成的SSH公钥文件内容复制到远程服务器,输入yes回车,并输入远程服务器的oracle用户的密码。见下图所示,
下面用SSH命令直接连接远程服务器,如下图,
在配置了本地服务器SSH信任远程服务器的功能以后,下面把通过SCP命令远程复制EXPDP文件的SH脚本内容展示一下,嘿嘿!
由于该SH脚本内容过多,所以我把它分成四部分来介绍,
1.个人信息(算是给自己做一个宣传吧)、脚本的名字和一些功能介绍以及使用注意事项,见下图,
2.导入Oracle用户下的.bash_profile环境配置文件和定义所有要使用的SHELL外部变量所在绝对路径的全局变量,见下图所示,
3.切换到DMP文件所在的目录、定义 当前日期和DMP文件所在目录总容量的SHELL全局变量、远程服务器磁盘字符串、SCP命令生成的LOG文件等,见下图,
4.定义全局函数SCP_EXPDP_PARALLEL(带并行导出DMP文件的SCP复制功能),并在最后进行调用它,见下图,
其中,有3点需要关注,
(1)在整个函数里,使用了两层FOR循环,外层是用来切换 远程服务器 的下一块磁盘,内层是用来复制 当天生成的DMP文件内容,并把前一天的DMP文件全部清除,因为本地服务器的磁盘存储空间有限,采用只保留当天的DMP文件,所以每次查看EXPDP目录,你会发现只有一份当天的DMP文件,这样也就达到了我要实现的目的。
(2)红色标注的那个IF条件判断语句,就是我在前面说明的磁盘空间容量比较,如果远程服务器上当前所在磁盘的剩余可用空间容量 大于 本地服务器上当天的DMP文件总容量,就把DMP文件复制到这块磁盘,否则,就执行else语句里的continue命令,即跳出本次内层for循环,读取下一块磁盘,把DMP文件复制到下一块磁盘。
(3)SCP命令在执行过程中的复制进度百分比是在每时每刻都变化着的,这个过程是无法直接写到LOG日志文件里的,不信大家试一试?这里,必须用SCRIPT命令随时抓取SCP命令执行的变化值并记录到相应的LOG日志文件,即在SCRIPT命令后面使用“-a参数 LOG文件位置”来实现将变化值追加写到LOG文件,而在SCRIPT命令后面使用“-c参数 SCP命令”来实现远程复制操作。
以上就是我分享的全部内容,另外,我把那个SHELL脚本scp_expdp_parallel_local_to_remote.sh的源代码,大家如果需要可自行下载。
------------------------------------------分割线------------------------------------------
具体下载目录在 /2017年资料/11月/11日/利用Shell脚本实现将Oracle数据库的每日EXPDP导出文件复制到远程服务器/
------------------------------------------分割线------------------------------------------