2.3 克隆数据库

数据文件具备了,接下来是通过这些文件“克隆”一个数据库,这个工作由cloneDBCreation. sql脚本继续执行,这个脚本更为复杂,下面分开介绍一下。对于数据库的恢复

 

首先根据指定的数据库名称(测试数据库指定的名称为 eygle)创建一个控制文件,创建方式为RESETLOGS模式:

SET VERIFY OFF

connect "SYS"/"&&sysPassword" as SYSDBA

set echo on

spool D:\Oracle\admin\eygle\scripts\cloneDBCreation.log append

Create controlfile reuse set database "eygle"

MAXINSTANCES 8

MAXLOGHISTORY 1

MAXLOGFILES 16

MAXLOGMEMBERS 3

MAXDATAFILES 100

Datafile

'D:\Oracle\oradata\eygle\SYSTEM01.DBF',

'D:\Oracle\oradata\eygle\SYSAUX01.DBF',

'D:\Oracle\oradata\eygle\UNDOTBS01.DBF',

'D:\Oracle\oradata\eygle\USERS01.DBF'

LOGFILE GROUP 1 ('D:\Oracle\oradata\eygle\redo01.log') SIZE 51200K,

GROUP 2 ('D:\Oracle\oradata\eygle\redo02.log') SIZE 51200K,

GROUP 3 ('D:\Oracle\oradata\eygle\redo03.log') SIZE 51200K RESETLOGS;

创建了控制文件后,数据库随之MOUNT加载,这一步骤是为了以下工作的进行。

通过dbms_backup_restore包清空dbid等信息:

exec dbms_backup_restore.zerodbid(0);

这里再次使用到了dbms_backup_restore 包,zeroDbid 是包中的一个过程,用于清空数据文件头的部分信息,新的dbid在之后的控制文件创建时可以被计算,对于数据库克隆,这是必须的。

zeroDbid有一个输入参数,即文件号:

PROCEDURE zeroDbid(fno IN binary_integer);

当 fno==0 时,控制文件中包含的所有数据文件头都将被清零,zeroDbid 主要用于清除数据文件头的 3类信息:Database id信息、Checksum信息和Checksum符号位信息。

继续看这个脚本,清零完成之后,数据库重新启动,控制文件被重新创建,此时新的dbid被计算并最终写入新创建的控制文件中:

shutdown immediate;

startup nomount pfile="D:\Oracle\admin\eygle\scripts\initeygleTemp.ora";

Create controlfile reuse set database "eygle"

MAXINSTANCES 8

MAXLOGHISTORY 1

MAXLOGFILES 16

MAXLOGMEMBERS 3

MAXDATAFILES 100

Datafile

'D:\Oracle\oradata\eygle\SYSTEM01.DBF',

'D:\Oracle\oradata\eygle\SYSAUX01.DBF',

'D:\Oracle\oradata\eygle\UNDOTBS01.DBF',

'D:\Oracle\oradata\eygle\USERS01.DBF'

LOGFILE GROUP 1 ('D:\Oracle\oradata\eygle\redo01.log') SIZE 51200K,

GROUP 2 ('D:\Oracle\oradata\eygle\redo02.log') SIZE 51200K,

GROUP 3 ('D:\Oracle\oradata\eygle\redo03.log') SIZE 51200K RESETLOGS;

注意,在启动数据库时Oracle使用了一个临时的参数文件initeygleTemp.ora,在这个参数文件的最后一行设置了一个内部参数:

C:\Oracle\admin\eygle.t\scripts>tail -1 initeygleTemp.ora

_no_recovery_through_resetlogs=true

_no_recovery_through_resetlogs这个参数的作用是什么呢?可以从数据库中找到一点说明:

SQL> SELECT x.ksppinm NAME, y.ksppstvl VALUE, x.ksppdesc describ

2 FROM SYS.x$ksppi x, SYS.x$ksppcv y

3 WHERE x.inst_id = USERENV ('Instance')

4 AND y.inst_id = USERENV ('Instance')

5 AND x.indx = y.indx AND x.ksppinm LIKE '%&par%';

Enter value for par: no_reco

NAME VALUE DESCRIB

------------------------------ ----- ----------------------------------------------

_no_recovery_through_resetlogs FALSE no recovery through this resetlogs operation

这个参数用于限制恢复能否跨越resetlogs,对于数据库的恢复来说,resetlogs通常意味着不完全恢复,在数据库resetlogs打开之后,控制文件中的很多信息被改写,在Oracle 10g之前,如果数据库resetlogs打开,那么将不再能够通过当前的控制文件再次进行resetlogs点之前的恢复,而Oracle 10g改变了这个历史。

在Oracle 10g中,即使通过 resetlogs方式打开了数据库,Oracle仍然支持再次从 resetlogs时间点之前进行恢复;在Clone数据库时,Oracle设置这个参数为True,意思就是不允许再次进行跨越resetlogs时间点的恢复。关于这部分内容,我们将在后面章节进行更为详细的介绍。

继续解读这个脚本,接下来Oracle设置 restricted session模式,resetlogs打开数据库,然后删除了基于种子数据库的两个服务:

alter system enable restricted session;

alter database "eygle" open resetlogs;

exec dbms_service.delete_service('seeddata');

exec dbms_service.delete_service('seeddataXDB');

接下来修改global_name,添加临时文件等:

alter database rename global_name to "eygle";

ALTER TABLESPACE TEMP ADD TEMPFILE 'D:\Oracle\oradata\eygle\TEMP01.DBF' SIZE 20480K REUSE AUTOEXTEND ON NEXT 640K MAXSIZE UNLIMITED;

select tablespace_name from dba_tablespaces where tablespace_name='USERS';

alter system disable restricted session;

由于种子数据库的字符集通常与用户要求的不符,接下来 Oracle 通过内部操作强制更改了字符集、国家字符集(这个内容在后面的章节有详细的介绍):

alter database character set INTERNAL_CONVERT ZHS16GBK;

alter database national character set INTERNAL_CONVERT AL16UTF16;

最后修改用户口令,禁用 restricted session模式,这个克隆过程执行完毕:

alter user sys identified by "&&sysPassword";

alter user system identified by "&&systemPassword";

alter system disable restricted session;

至此,种子数据库已经按照用户的意图脱胎换骨得以重生。