本节书摘来自异步社区出版社《循序渐进oracle:数据库管理、优化与备份恢复》一书中的第1章,第1.4节,作者:盖国强,更多章节内容可以访问云栖社区“异步社区”公众号查看。
循序渐进oracle:数据库管理、优化与备份恢复
前面提到,除了定制数据库之外,还可以使用模板来创建数据库,接下来就让我们一起来了解一下使用模板创建数据库的过程。
在1.1节中,我们提到可以通过命令行启动dbca工具,可能更多的朋友是通过“开始”菜单中oracle创建的快捷菜单来启动dbca的,如图1-25所示,右图则是快捷方式的具体指向。

注意到这个快捷项的目标执行的是以下命令:
此处的dbca.cl文件和前面的dbca.bat批处理文件执行的功能是一致的:
那么dbca为什么指向这个目录呢?这个目录又是做什么用的呢?
实际上这个目录是oracle的缺省模板目录,当使用模板来创建数据库时,就用到了这个目录下的文件。
下面来看一下使用模板创建数据库的过程。
使用模板和前面的过程主要不同之处在于第二个步骤,在这里选择“定制数据库”之外的选项,就都使用了模板,并且包含了数据文件(eygle模板是我们之前保存的),如图1-26左图所示;使用模板创建数据库通常速度都会很快,原因就在于数据文件是从种子数据库中恢复出来的,而不需要创建文件及字典对象等信息,右图展示创建过程的第一个步骤就是“复制数据库文件”。
这里通过脚本说明一下通过模板创建数据库和定制数据库的不同。
首先eygle.sql脚本记录如下内容:
该脚本首先调用的是clonermanrestore.sql脚本,该脚本记录如下内容:
这个脚本首先启动实例到nomount模式,然后调用rmanrestoredatafiles.sql来恢复文件。
rmanrestoredatafiles.sql脚本是通过系统包dbms_backup_restore来恢复备份集中的文件,从而实现数据恢复,其主要内容如下:
[oracle@jumper conner] $ sqlplus "/ as sysdba"
connected to an idle instance.
sql> startup nomount;
oracle instance started.
sql> declare
2 devtype varchar2(256);
3 done boolean;
4 begin
5 devtype:=sys.dbms_backup_restore.deviceallocate (type=>'',ident=>'t1');
6 sys.dbms_backup_restore.restoresetdatafile;
7 sys.dbms_backup_restore.restoredatafileto(dfnumber=>01,
toname=>'/opt/oracle/oradata/conner/system01.dbf');
8 sys.dbms_backup_restore.restoredatafileto(dfnumber=>02,
toname=>'/opt/oracle/oradata/conner/undotbs01.dbf');
9 sys.dbms_backup_restore.restoredatafileto(dfnumber=>03,
toname=>'/opt/oracle/oradata/conner/users01.dbf');
10 sys.dbms_backup_restore.restorebackuppiece(done=>done,
handle=>'/opt/oracle/product/9.2.0/dbs/0ggmiabq_1_1', params=>null);
11 sys.dbms_backup_restore.devicedeallocate;
12 end;
13 /
pl/sql procedure successfully completed.
sql> alter database backup controlfile to trace;
database altered.
可以找到trace文件,编辑、执行重建控制文件的需要部分:
sql> set echo on
sql> @ctl.sql
sql> create controlfile reuse database "conner" resetlogs archivelog
2 -- set standby to maximize performance
3 maxlogfiles 5
4 maxlogmembers 3
5 maxdatafiles 100
6 maxinstances 1
7 maxloghistory 1361
8 logfile
9 group 1 '/opt/oracle/oradata/conner/redo01.log' size 10m,
10 group 2 '/opt/oracle/oradata/conner/redo02.log' size 10m,
11 group 3 '/opt/oracle/oradata/conner/redo03.log' size 10m
12 -- standby logfile
13 datafile
14 '/opt/oracle/oradata/conner/system01.dbf',
15 '/opt/oracle/oradata/conner/undotbs01.dbf',
16 '/opt/oracle/oradata/conner/users01.dbf'
17 character set zhs16gbk
18 ;
control file created.
sql> recover database using backup controlfile until cancel;
ora-00279: change 240560269 generated at 06/09/2005 17:33:48 needed for thread 1
ora-00289: suggestion : /oradata/conner/archive/1_7.dbf
ora-00280: change 240560269 for thread 1 is in sequence #7
specify log: {=suggested | filename | auto | cancel}
auto
ora-00279: change 240600632 generated at 06/10/2005 10:42:26 needed for thread 1
ora-00289: suggestion : /oradata/conner/archive/1_8.dbf
ora-00280: change 240600632 for thread 1 is in sequence #8
ora-00278: log file '/oradata/conner/archive/1_7.dbf' no longer needed for this recovery
ora-00279: change 240620884 generated at 06/10/2005 10:45:42 needed for thread 1
ora-00289: suggestion : /oradata/conner/archive/1_9.dbf
ora-00280: change 240620884 for thread 1 is in sequence #9
ora-00278: log file '/oradata/conner/archive/1_8.dbf' no longer needed for this recovery
ora-00283: recovery session canceled due to errors
ora-00600: internal error code, arguments: [3020], [4242465], [1], [9], [314], [272], [], []
ora-10567: redo is inconsistent with data block (file# 1, block# 48161)
ora-10564: tablespace system
ora-01110: data file 1: '/opt/oracle/oradata/conner/system01.dbf'
ora-10560: block type 'data segment header - unlimited'
ora-01112: media recovery not started
ora-00279: change 240620949 generated at 06/10/2005 10:45:44 needed for thread 1
ora-00280: change 240620949 for thread 1 is in sequence #9
cancel
media recovery cancelled.<code>`</code>
恢复到最后可用日志后,通过resetlogs方式打开数据库:
至此恢复完成。这是一次常规恢复,dbms_backup_restore的功能远不止于此,还可以通过该包恢复备份集中的控制文件、归档日志等文件。
继续前面的讨论,rmanrestoredatafiles.sql脚本通过dbms_backup_restore包从种子文件seed_database.dfb恢复出数据文件,来看一下模板目录中存放的模板和种子数据库(自定义的模板也存放在这个目录中):
seed_database.dfb文件就是包含种子文件的一个备份集。
数据文件具备了,接下来是通过这些文件“克隆”一个数据库,这个工作由clonedbcreation.sql脚本继续执行,这个脚本更为复杂,下面分开介绍一下。
首先根据指定的数据库名称(测试数据库指定的名称为eygle)创建一个控制文件:
然后通过dbms_backup_restore包清空dbid等信息:
看到这里再次使用到了dbms_backup_restore包,zerodbid是包中的一个过程,用于清空数据文件头的部分信息,新的dbid在之后的控制文件创建时可以被计算,对于数据库克隆,这是必须的。
zerodbid有一个输入参数,即文件号:
当fno==0时,控制文件中包含的所有数据文件头都将被清零,zerodbid主要用于清除数据文件头的3类信息:database id信息、checksum信息和checksum符号位信息。
继续看这个脚本,清零完成之后,数据库重新启动,控制文件被重新创建,此时新的dbid被计算并最终写入所有数据文件:
注意,在启动数据库时oracle使用了一个临时的参数文件initeygletemp.ora,在这个参数文件的最后一行设置了一个内部参数:
_no_recovery_through_resetlogs这个参数的作用是什么呢?可以从数据库中找到一点说明:
这个参数用于限制恢复能否跨越resetlogs,对于数据库的恢复来说,resetlogs通常意味着不完全恢复,在数据库resetlogs打开之后,控制文件中的很多信息被改写,在oracle 10g之前,如果数据库resetlogs打开,那么将不再能够通过当前的控制文件再次进行resetlogs点之前的恢复,而oracle 10g改变了这个历史。
在oracle 10g中,即使通过resetlogs方式打开了数据库,oracle仍然支持再次从resetlogs时间点之前进行恢复;在clone数据库时,oracle设置这个参数为true,意思就是不允许再次进行跨越resetlogs时间点的恢复。关于这部分内容,我们将在后面章节进行更为详细的介绍。
继续解读这个脚本,接下来oracle设置restricted session模式,resetlogs打开数据库:
至此,种子数据库已经按照用户的意图脱胎换骨得以重生。
在很多oracle文档中,可能大家都注意过oracle用来进行测试的一个表空间,这个表空间中有一系列预置的用户和数据,可以用于数据库或bi的很多测试实验。
这个表空间在使用模板建库时是可以选择的,在如图1-27所示的这个界面中,可以选择建库时包含这个范例表空间(缺省是未选择的)。
如果选择了包含示例方案,则clonedbcreation.sql脚本将会有所改变,主要增加了如下语句:
看到这里,再次引用了模板目录中的文件:
通过mkplug.sql脚本来加载这个范例表空间,来看一下这个脚本的主要内容。
同样,最重要的是通过dbms_backup_restore包从example01.dfb文件中恢复数据文件:
这个恢复完成之后,接下来最重要的部分就是通过传输表空间技术将example表空间导入到当前的数据库。
考虑一下这种情况,当进行跨数据库迁移时,需要将一个用户表空间中的数据迁移到另外一个数据库,应该使用什么样的方法呢?
最常规的做法可能是通过exp工具将数据全部导出,然后在目标数据库上imp导入,可是这种方法可能会比较缓慢。exp工具同时还提供另外一种技术——可传输表空间技术,可以用于加快这个过程。
在exp -help的帮助中,可以看到这样一个参数:
通过这个选项,我们可以对一组自包含、只读的表空间只导出元数据,然后在操作系统层将这些表空间的数据文件拷贝至目标平台,并将元数据导入数据字典(这个过程称为插入,plugging),即完成迁移。但是注意,传输表空间技术不能应用于system表空间或sys用户拥有的对象。
对于可传输表空间有一个重要概念:自包含(self-contained)。
在表空间传输中,要求表空间集为自包含的,自包含表示用于传输的内部表空间集没有引用指向外部表空间集。自包含分为两种:一般自包含表空间集和完全(严格)自包含表空间集。
常见的以下情况是违反自包含原则的。
boll 索引在内部表空间集,而表在外部表空间集(相反地,如果表在内部表空间集,而索引在外部表空间集,则不违反自包含原则)。
boll 分区表一部分区在内部表空间集,一部分在外部表空间集(对于分区表,要么全部包含在内部表空间集中,要么全不包含)。
boll 如果在传输表空间时同时传输约束,则对于引用完整性约束,约束指向的表在外部表空间集,则违反自包含约束;如果不传输约束,则与约束指向无关。
boll 表在内部表空间集,而lob列在外部表空间集,则违反自包含约束。
通常可以通过系统包dbms_tts来检查表空间是否自包含,验证可以以两种方式执行:非严格方式和严格方式。
以下是一个简单的验证过程,假定在eygle表空间存在一个表eygle,其上存在索引存储在users表空间:
以sys用户执行非严格自包含检查(full_check=false):
执行严格自包含检查(full_check=true):
反过来对于users表空间来说,非严格检查也是无法通过的:
但是,可以对多个表空间同时传输,则一些自包含问题就可以得到解决:
表空间自包含确认之后,进行表空间传输就很方便了,一般包含如下几个步骤。
(1)将表空间设置为只读。
(2)导出表空间。在操作系统提示符下执行:
此处的导出文件只包含元数据,所以导出文件很小,导出速度也会很快。
(3)转移。将导出的元数据文件(此处是exp_users.dmp)和传输表空间的数据文件(此处是users表空间的数据文件user01.dbf)转移至目标主机(转移过程如果使用ftp方式,应该注意使用二进制方式)。
(4)传输。在目标数据库将表空间插入到数据库中,完成表空间传输。在操作系统命令提示符下执行以下语句:
了解了oracle的可传输表空间技术后,来看一下example表空间的插入,以下脚本仍然来自mkplug.sql脚本:
完成plugging之后,这个表空间就被包含在了新建的数据库之中。
需要注意的是,在oracle 10g之前,数据文件是不能够跨平台传输使用的,从oracle 10g开始,oracle支持跨平台的表空间传输,这极大地增强了数据迁移的便利性。
1.字节顺序和平台
数据文件所以不能跨平台,主要是由于不同平台的字节顺序不同,这是计算机领域由来已久的问题之一,在各种计算机体系结构中,由于对于字、字节等的存储机制有所不同,通信双方交流的信息单元(比特、字节、字、双字等)应该以什么样的顺序进行传送就成了一个问题,如果不达成一致的规则,通信双方将无法进行正确的编/译码从而导致通信失败。
目前在各种体系的计算机中通常采用的字节存储机制主要有两种:big-endian和little-endian。
一些操作系统(包括windows)在低位内存地址中存放二进制数据的最低有效字节,因此这种系统被称为little endian;一些操作系统(包括solaris)将最高有效字节存储在低位内存地址中,因此这种系统被称为big endian。
举一个简单点的例子,假如1122这样一个数据要存入不同系统,对于little endian的系统,存储的顺序就是2211,小头在前;而对于big endian的系统来说,存储顺序就是1122,大头在前,显然big endian更符合我们通常的语言习惯。
那么跨平台的问题就出现了,当一个little endian的系统试图从一个big endian的系统中读取数据时,就需要通过转换,否则不同的字节顺序将导致数据不能被正确读取。
说明:
据考证,endian这个词来源于jonathan swift在1726年写的讽刺小说《gulliver's travels》(《格利佛游记》)。该小说在描述gulliver畅游小人国时碰到了如下的一个场景。在小人国里的小人因为非常小(身高6英寸)所以总是碰到一些意想不到的问题。有一次因为对水煮蛋该从大的一端(big-end)剥开还是小的一端(little-end)剥开的争论而引发了一场战争,并形成了两支截然对立的队伍:支持从big-end剥开的人swift就称作big-endians,而支持从little-end剥开的人就称作little-endians(后缀ian表明的就是支持某种观点的人)。endian这个词由此而来。
清楚了这个问题,接下来就可以来看看oracle是如何处理这种情况的。
2.源平台和目标平台
首先在迁移之前,需要确认一下源平台和目标平台的平台信息,这些信息可以通过视图v$transportable_platform和v$database视图联合查询得到。
以下是源平台的信息:
查询目标数据库平台信息:
看到windows平台和solaris平台的字节顺序是不同的,windows平台是little-endian,而solaris平台是big-endian的。
可以通过数据库查询oracle 10g支持的平台转换:
3.源平台的导出及转换
接下来开始我们的测试,创建一个独立的自包含表空间,并创建一个测试表:
将表空间设置为只读:
导出要传输的表空间:
使用rman的convert命令转换文件格式:
确认导出文件已生成:
4.文件传输
通过ftp获得两个文件,注意应该使用二进制方式传输(bin模式):
注意:
此处也可以在imp时通过fromuser/touser参数将数据导入其他用户下。
现在这个表空间已经被插入到新的数据库中,并且数据全部传输过来:
导入后的表空间还处于read only状态,确认后可以更改为读写模式:
表空间已更改。
同样,传输表空间也可以通过数据泵来完成,以下是oracle 10gr1中插入表空间的简单示例:
6.同字节序文件的跨平台
前面说过,当一个little endian的系统试图从一个big endian的系统中读取数据时,就需要通过转换,否则不同的字节顺序将导致数据不能被正确读取。那么另外一个问题出现了,如果字节序相同的平台进行文件交互,数据能否被正确读取呢?
理论上的确是可以的,但是由于在不同的平台上操作系统会在数据文件头写上系统信息,这部分信息无法跨越平台,所以仍然会导致跨平台的文件无法被数据库正确识别(oracle10g中同字节序平台数据文件头不再存在跨平台的迁移问题)。
接下来让我们通过windows和linux平台来进行一个跨平台测试,相信通过这个测试可以对以上提出的问题作出一个很好的回答。
实验环境一:windows xp + oracle10g 10.2.0.1。
实验环境二:red hat enterprise linux as release 3 + oracle 9ir2 9.2.0.4。
看一下linux平台,文件头被操作系统保留了8192字节:
windows平台上数据文件头同样保留了8192字节:
可以通过linux和windows平台来进行一个小测试实验,这两个平台都是little endian的系统:
首先在linux下oracle 9204中创建一个测试表空间:
创建测试用户并创建一个测试表:
压缩文件以方便传输:
导出表空间:
传输文件到windows平台:
在windows上创建新用户:
其中“参数:[krhcvt_filhdr_v10_01]”提示文件头无法正确识别。
可以通过对这个文件进行一个特殊操作,为文件更换一个windows下数据文件的文件头,则数据文件就应该能够被数据库识别。以下是这个“小手术”操作的过程。
首先提取一个windows数据文件头:
然后去除linux下的数据文件头:
最后将这两个文件合二为一:
d:oradataeygledatafile>copy /b header.dbf+eyglee.dbf eygleee.dbf
header.dbf
eyglee.dbf
已复制 1 个文件。
现在拥有的新文件eygleee.dbf就具有了一个windows平台的文件头以及linux下的“文件身”。至此这个文件就能够被windows上的oracle识别了,可以执行导入操作:
经由常规路径由 export:v09.02.00 创建的导出文件
即将导入可传输的表空间元数据...
已经完成 zhs16gbk 字符集和 al16utf16 nchar 字符集中的导入
. 正在将 sys 的对象导入到 sys
. 正在将 eyglee 的对象导入到 eyglee
. . 正在导入表 "eyglee"
成功终止导入, 没有出现警告。
此时数据已经能够被正确识别:
最后将表空间更改为读写模式,可以进行正常的数据操作:
通过这个实验,还可以得出另外一个结论,oracle 9i的数据文件可以通过表空间传输迁移到oracle 10g中使用。
7.oracle10g同字节序跨平台迁移
在oracle10g中,同字节序跨平台的文件头信息oracle会自动改写,不再需要转换。我们看以下测试:
导出元数据,准备表空间迁移:
然后我们可以直接将这两个文件传输到windows平台上,在数据库中执行必要的准备步骤:
接下来执行导入:
boll 重做日志文件和控制文件不会传输,迁移之后需要重建控制文件使用resetlogs方式打开数据库;临时文件不会被传输。
boll bfiles、外部表和directories、口令文件等不会被传输。
我们通过linux平台到windows平台的迁移来看一下这一技术的实现。
(1)确认平台及版本。
首先要确定源平台和目标平台具有相同的字节序:
然后需要确定源平台及目标平台的数据库版本,通常需要这两者具有相同的数据库版本,本例的情况有所不同,linux平台的数据库版本为10.2.0.1,windows平台的数据库版本为10.2.0.3,数据库版本不同将使情况稍微复杂一点,而且需要注意的是,通常高版本的数据库不能向低版本迁移。
(2)确认迁移是否支持。
跨平台迁移需要数据库处于read only模式打开,使用dbms_tdb.check_db进行检查:
如果以上过程成功执行,并没有其他相关警告输出,则说明数据库可以支持跨平台转移。
(3)检查外部对象。
使用dbms_tdb.check_external来识别外部表、directories或bfiles等,这些对象所指向的外部数据不能被rman自动转移。
如果数据库中存在外部表、directories等,则以上过程执行后的输出与以上类似。
(4)使用rman进行跨平台文件迁移。
执行跨平台迁移首先要通过rman对数据文件进行转换,rman执行过程如下:
最后rman还自动生成一个参数文件,这个文件是init_00il1i4r_1_0.ora,这个参数文件里包含了一些重要的初始化参数,可以根据需要进行相应的更改,由于平台以及路径的不同,很多涉及路径的参数都需要进行变更,这个参数文件的内容大致分为3个部分。
第一部分列出需要修改的参数:
第二部分列出了建议review的参数:
第三部分列出了来自于源数据库的一些特殊设置,这些参数可以酌情修改:
参数文件的内容我们可以在新的平台上重新创建,这个参数文件可以作为参考。
(5)转移文件到目标平台。
源平台的工作完成之后,数据文件可以通过ftp等方式转移到目标平台,部署到相应目录,我的操作步骤如下:
(6)创建基础环境。
首先创建相关目录:
创建windows数据库服务:
实例已创建。
修改参数文件,参数文件可以从前面自动生成的参数文件进行修改得到,其中目录结构需要依据新平台的具体设置进行修改,和存储主要相关的两个参数修改如下:
如果我们计划使用omf管理,可以暂时注释这一参数,在创建控制文件后再将控制文件的名称路径追加到参数文件中。
(7)迁移步骤。
准备工作完成之后,我们可以进行新平台的数据库加载等工作,这些工作还可以参考在源平台生成的transport.sql脚本。
这个脚本的第一部分给出了使用参数文件启动实例及重新创建控制文件的语法参考,当然我们还需要修改才能使用这段脚本:
由于我们已经编辑好了新的参数文件,可以使用这个参数文件启动实例:
接下来创建控制文件:
然后将控制文件的名称等信息追加到参数文件中:
sql> host "echo &ctl_files >>c:oracle10.2.0databaseinitjulia.ora";
执行完以上命令后,需要检查参数文件的格式,如果控制文件名称未正确添加,可以手工调整一下。
完成了以上工作后,可以关闭数据库,再次启动数据库到mount状态,这时候新的控制文件已经发挥作用:
(8)完成数据库恢复。
接下来再参考一下transport.sql中的推荐步骤:
现在我们需要通过resetlogs方式来重新生成日志文件,然后手工添加临时文件。
注意,在迁移过程中如果两个平台的数据库版本完全一致,则以上步骤可以顺利执行,参考transport.sql可以顺利完成迁移。而本例的测试平台由于linux平台的数据库版本为10.2.0.1,windows平台版本为10.2.0.3,所以实际操作中还会有所不同,在执行resetlogs过程中,数据库会发生中断:
第 1 行出现错误:
ora-01092: oracle 实例终止。强制断开连接
检查日志我们发现以下提示:
mon jun 25 10:03:19 2007
errors in file c:oracleadminjuliaudumpjulia_ora_3596.trc:
ora-00704: 引导程序进程失败
ora-39700: 必须用 upgrade 选项打开数据库
oracle要求以upgrade选项打开数据库,对数据库执行跨版本迁移。
我们继续参考transport.sql的最后部分:
再次启动数据库到upgrade模式,由于之前的数据库中断,现在这些需要进行一点恢复工作:
执行脚本?/rdbms/admin/utlirp.sql,这个脚本执行完成之后会有如下提示:
也就是说,这个脚本的作用是使数据库中的pl/sql对象invalid,然后通过utlrp.sql的重新编译,消除跨平台的兼容性影响。
按照transport.sql脚本提示的步骤,我们可以重新启动数据库来执行utlrp.sql脚本(由于本例涉及版本迁移,需要再次启动数据库到upgrade模式,如果数据库版本相同,则可以直接启动数据库,执行utlrp.sql脚本完成最后的编译工作):
这个脚本调用catlog.sql和catproc.sql来重建字典对象等,在执行完这个脚本之后,我们可以关闭数据库后,正常打开数据库:
catupgrd.sql脚本可能会使部分字典对象失效,我们可以再次运行utlrp.sql脚本来进行编译,编译完成后,不要忘记为数据库添加临时文件:
至此,同字节序的跨平台迁移全部完成,当然由于版本的不同,整个过程稍微复杂了一些,不过,这个过程对于跨平台的迁移及版本升级是一个很好的参考。
9.实现数据迁移的高可用性
通过以上测试实际上可以确认,对于可传输表空间,可以很容易从oracle 9i向oracle 10g迁移。那么这种方法对于可用性要求极高的环境进行数据迁移或数据库迁移具有极大的便利。
如果进行数据库升级,通常的方法是通过dbua(database upgrade assistant,oracle 10g引入的新工具)进行,但是dbua存在的问题在于,操作过程过长,而且如果升级过程中出现问题,数据文件可能不能重新被使用,这就需要从备份中进行恢复,这使得业务连续性要求高的企业很难采用这种方法进行升级。
另外一种常见的迁移方法是通过逻辑导出导入(exp/imp),但是这种方法对于不断变化的数据无能为力,所以通常也不可行。那么现在,可传输表空间就成了一个可以考虑的快速迁移或升级方法。
oracle有一个小组,专注于设计高可用性架构的实现,以帮助用户最大限度的提高系统可用性,oracle有一个专有名词用来命名这类技术——maa(maximum availability architecture ,maa)。otn上maa部分有一个amadeus公司的实践案例,通过可传输表空间从oracle 9i向oracle 10g实现快速数据迁移。
当然,这种方法的使用要考虑的还有很多,通过各种技术和方法的结合使用才能最终地达到快速迁移的目标。
amadeus公司的迁移是在同类型平台不同主机之间进行的,其实现步骤大致如下:
(1)在升级主机安装oracle 9i版本,并创建生产库的dataguard数据库,这个工作可以在线进行,不影响主节点的工作。
(2)在升级主机安装oracle 10gr2数据库软件,创建数据库;此时升级主机上存在了2个数据库。
(3)整理不能通过transport tablespace处理的内容,如sequence、synonyms、grants等。
(4)在升级割接时间,将主库置为只读,将日志全部应用到备机,业务影响从此时开始。
(5)将备机的数据文件通过可传输表空间迁移至oracle 10gr2数据库,并创建sequencee、synonyms、grants等对象,检查验证。
(6)如果没有问题,则即可将业务切换至新的oracle 10gr2数据库运行,业务恢复正常运行。
在这个迁移过程中,如果迁移失败,那么直接读写打开主库即可恢复业务的正常运行,回退非常方便。
使用这种方法,业务影响仅发生在以上(4)~(6)步,在otn的案例中,amadeus公司在实际操作中,10分钟之内就将一个大型数据库迁移到oracle 10gr2,这种方式是一种非常有新意的创新性应用。在熟悉了oracle的各项技术之后,通过不断实践和探索,我们就能够不断发现充满价值的oracle应用。
在进行表空间迁移时,如果是从文件系统到文件系统的迁移很容易实现,但是如果是从文件系统到asm则需要多一点步骤。类似前面的测试,如果在asm环境中执行同样的导入命令:
则简单的导入之后会出现如下的效果,新导入的文件位于文件系统之上,这显然是不希望看到的,我们需要将文件系统文件转移到asm磁盘组上去:
文件转移可以通过rman来进行,但是首次尝试遇到了rman-20201错误:
这个错误是由于trans表空间刚刚导入到数据库中,处于只读状态,并未被catalog记录感知,通过对这个文件进行特定操作,如读写变更,则可以消除此错误:
rman中的schema信息尚未记录该表空间:
在数据库内部对该表空置读写访问:
接下来将表空间状态再改为只读:
通过rman进行镜像拷贝:
切换之前需要将表空间离线,否则会出现错误:
将表空间离线:
现在转换后的表空间已经被转移到了asm磁盘组中,此时可以将表空间online,如果操作期间有过事务变更,还可能需要恢复:
从oracle 10g开始,oracle提供了dbms_file_transfer程序包,可以很方便地在本地数据库和远程数据库,asm和文件系统间传输数据库文件。
有了dbms_file_transfer,数据库文件的传输就方便了许多,尤其是在传输基于asm存储的数据文件时,不再局限于利用rman来进行传输,为我们提供了更多的选择。
注意,dbms_file_transfer具备一定的限制,单个数据库文件必须是512字节的整数倍,并且文件大小必须小于或者等于2tb,但是这基本上算不上什么弱点,我们的绝大多数需求都可以被满足。
dbms_file_transfer包一共包含了3个存储过程,分别提供本机之间拷贝(copy_file)、本机从远程主机获取(get_file)以及本机上传至远程主机(put_file)3种传输数据库文件的功能。
以上过程的参数中,除了文件名称外,最关键的是directory目录参数,这个目录需要预先设定,并且要求传输用户对相应的目录具有读或者写的权限。
看以下测试,首先通过asmcmd在datadg下创建一个asmbk目录:
现在dbms_file_transfer就可以大显身手,快速地帮助我们解决文件传输的问题:
看一下asm磁盘组上的内容,实际上文件的位置是在datafile下,asmbk下存放的是一个别名:
首先在远程数据库创建测试用户及目录,并进行授权:
接下来在本地数据库配置tnsnames.ora文件,并创建db link:
接下来就可以通过db link进行远程的文件操作了,put_file可以将文件传输至远程主机:
远程节点可以立刻检查到这个文件的存在:
进一步的,可以将远程文件读取到本地:
本地asm存储中,马上获得了这个文件:
而进一步的,将表空间置于热备模式下,可以通过dbms_file_transfer包将数据库热备到远程主机,甚至可以基于此来创建远程的dataguard数据库,有时在数据库巨大,备份恢复空间不足时,通过这种方式进行数据传输与备库创建未尝不是一种妙解:
dbms_file_transfer为我们提供了多一个选择和灵活性,很多时候,oracle一个小小的增强如果能够得到恰如其分的利用,就能够发挥巨大的优势。了解了oracle的种种可能之后,我们才能够灵活运用,如臂使指。
在oracle database 11g的创建脚本中,存在如下一个名为lockaccount.sql的脚本,该脚本在完成数据库创建之后,将部分用户账号锁定。一个简单的for循环完成了这个安全加固的工作:
1.4.10 最后的脚本
在完成了主要脚本的工作之后,剩下的是一些最后的维护工作。
这里还有两个脚本需要执行,首先执行的是postscripts.sql脚本,这个脚本主要对部分用户及部分数据库选件进行维护:
最后执行的脚本是postdbcreation.sql,在这个脚本中将创建spfile,解锁sysman、dbsnmp用户,编译失效对象并配置db control:
看到在最后部分,通过emca.bat批处理文件,配置了db control,这里通过一条完整的命令快速地完成了db control的创建等工作,也可以通过手工方式对db control进行维护,关于这部分的内容请参考“第2章 从oem到grid control”。
此外,需要注意的是以下几句命令:
在oracle 9i的postdbcreation.sql的脚本中,这部分的内容如下:
其实两者是相同的,utlrp.sql中主体部分与oracle 10g中是相同的:
oracle在utlrp.sql脚本的注释中说得很明确:这是一个通用脚本,可以在任意时候运行,以重新编译数据库失效对象。
通常我们会在oracle的升级指导中看到这个脚本,oracle强烈推荐在migration / upgrade / downgrade之后,通过运行此脚本编译失效对象。但是注意,此脚本需要用sql*plus以sysdba身份运行,并且当时数据库中最好不要有活动事物或ddl操作,否则极容易导致死锁的出现。
这样使用模板创建数据库就完成了。
1.4.11 使用模板建库注意事项
当使用模板创建数据库时,有一点需要特别注意,那就是种子数据库的版本。因为种子数据库通常来自软件的初始分布版本,如安装oracle database 9.2.0,则种子数据库就是随软件发布的初始版本。如果我们安装了9.2.0再安装patch 9.2.0.8,那么此后若使用模板种子数据库创建数据库,则数据库可能并不会自动升级为9.2.0.8的版本。
如此创建的数据库其banner显示为oracle 9i enterprise edition release 9.2.0.8.0:
而如果查询注册的组件会发现,大部分组件仍然是9.2.0.1的版本:
已选择15行。
在这样的模式下运行,数据库的状况是不可靠的,在某些条件下,因为这些组件的不完备,可能会出现错误。在以上的数据库环境中,当drop用户时可能会遇到如下错误:
解决该问题的方法就是运行一个升级重要脚本catpatch.sql,按照以下步骤操作:
之后可以查看patch.log日志文件来确认升级是否成功,如果成功完成,该日志末尾会显示相关组件版本:
所以在使用模板创建数据库时,一定要注意升级问题。