Oracle 数据库的Data Guard是实现数据库级别的数据灾备机制。它的原理类似数据库备份恢复过程中应用重做日志部分,不停地在备用节点服务器上应用从主库传过来的归档日志文件。
data guard的备用节点又细分成logical standby和physical standby,分别应用在不同的场景中。
在Oracle 10g的Data Guard环境中,备用节点和主库节点可以互相切换。这个功能的用途包括数据库灾备的验证、数据库硬件维护的无缝切换、因数据库服务器更换导致的数据迁移等等。
在以前我处理的数据迁移工作中,一直数据库的备份和异地恢复来完成。这种方案非常可靠,新环境中数据库配置等都不需要做特别修改。但是,如果新环境出现其他故障(网络故障)时,要再将新环境的数据库迁移回去,就不可能了。新环境数据库启用后,会很快有新数据进来。又再用方式做一次数据迁移,时间上也不允许。如果使用Oracle Data Gauard 来完成这个数据迁移工作,即使后来发现新环境有故障,我们也可以利用data guard的角色互换工作再切换到老环境中。
(miki西游 @mikixiyou 文档,原文链接: http://mikixiyou.iteye.com/blog/1561621 )
这个迁移操作分成两个部分,其一是将老环境的数据库和新环境的数据库配置成data guard模式,备库采用physical standby。其二是将主库切换成备库角色,备库又切换成主库角色。
其一,data guard环境搭建
在主库上修改初始化参数,保护级别采用默认值即最大性能,重做日志传输方式采用ARCH 。这里是做数据迁移,如果是灾备需求,则需要设置成最大可用或最大保护,传输重做日志的方式为LGWR SYNC AFFIRM 。
alter system set log_archive_config='dg_config=(mikidb,mikidg)' scope=memory; alter system set log_archive_dest_2='SERVICE=MIKIDB_STANDBY ARCH ASYNC AFFIRM VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=MIKIDG' scope=memory;
主库的tnsnames.ora 文件中需要增加一个tnsname ,即log_archive_dest_2 中指定的mikidb_standby 。
mikidb_STANDBY = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.64.1)(PORT = 1521)) ) (CONNECT_DATA = (SID = mikidb) ) )
在备库上修改初始化参数,设置db_unique_name ,fal_client 和fal_server 。
如下:
*.db_unique_name='mikidg'
*.fal_client='mikidb_standby'
*.fal_server='mikidb_primary'
fal 用于探测主库和备库之间归档日志文件的间隔,称之为fetch archive log 。
另外,归档路径也做一个简单设置,用于保存从主库上传输过来的归档日志文件。
*.log_archive_config='dg_config=(mikidb,mikidg)'
*.log_archive_dest_1='LOCATION=+VG1/ valid_for=(all_logfiles,all_roles) db_unique_name=mikidg'
备库的tnsnames.ora 文件中需要增加两个tnsname ,即fal_client 和fal_server 的值,分别是mikidb_standby 和mikidb_primary 。
mikidb_STANDBY = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.64.1)(PORT = 1521)) ) (CONNECT_DATA = (SID = mikidb) ) ) mikidb_primary = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.89.1)(PORT = 1521)) ) (CONNECT_DATA = (SID = mikidb) ) )
在主备库的初始化参数都设置好以后,我们在备库上恢复主库的备份,恢复使用控制文件需要主库特别生成,专门用于data guard 的备库应用。
在rman 下执行backup current controlfile for standby ‘/tmp/ctl.standby’; 就可以。
恢复的数据文件备份集就使用已有的最新的备份集。
登录RMAN 管理工具界面,执行恢复操作。
rman target /
restore controlfile from '/tmp/ctl.standby';
sql ‘alter database mount’;
catalog start with ‘/backup/’;
restore database;
recover database;
恢复到出错后,退出。
再登录sqlplus 界面,启用备库重做日志不间断应用模式。
alter database recover managed standby database disconnect from session;
通常,主库新生成的数据就会源源不断地通过归档日志文件传输过来,达到了数据迁移的目的。
其二,主库和备库的角色互换
1 、关闭所有主库上的客户端连接,准备主库角色切换
2 、在主库上,将其切换成备库角色
SQL> alter database commit to switchover to physical standby;
Database altered.
SQL> shutdown immediate
ORA-01507: database not mounted
ORACLE instance shut down.
以备用模式启用原主库
SQL> startup nomount;
ORACLE instance started.
SQL> alter database mount standby database;
SQL> select name,open_mode,PROTECTION_MODE,DATABASE_ROLE from v$database;
SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DISCONNECT FROM SESSION;
3 、在备库上,切换成主库模式。
SQL> alter database commit to switchover to primary;
SQL> shutdown immediate;
ORA-01507: database not mounted
ORACLE instance shut down.
SQL> startup
SQL> alter system switch logfile;
System altered.
再将初始化参数按照第一部分做一些修改,就实现了新环境和老环境的对调。如果新环境出现了问题,咱们再切换一次,就让应用再次使用老环境了。即使新环境又新生成了数据,那么老环境也因为是data guard 的物理备库模式,也同步过去了新数据。
总而言之,这将是一个更加靠谱的数据库迁移方案。
但,我想,它还有是有缺陷的。有哪些缺陷呢?
附参考命令
-- Make sure that nobody accesses the primary database anymore sqlplus@master> SHUTDOWN IMMEDIATE sqlplus@master> STARTUP [RESTRICT] -- Prepare the SwitchOver sqlplus@master> ALTER DATABASE COMMIT TO SWITCHOVER TO STANDBY WITH SESSION SHUTDOWN; sqlplus@standby> ALTER DATABASE COMMIT TO SWITCHOVER TO PRIMARY; -- Do it sqlplus@master> SHUTDOWN IMMEDIATE sqlplus@master> STARTUP MOUNT sqlplus@master> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DISCONNECT; sqlplus@standby> ALTER DATABASE OPEN
sqlplus@standby> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE FINISH;
sqlplus@standby> ALTER DATABASE COMMIT TO SWITCHOVER TO PRIMARY; |
failover操作过程
备库端:
如果是最大保护和最大可用性模式,则可以直接在备库端执行failover切换。如果是最大性能模式,为了尽可能减少数据丢失,需要检查主库是否有日志没有传输到备库,手动传输备库进行注册和恢复。注意RAC环境下,归档日志是分线程的。
SYS@dev01dg>select distinct thread#,max(sequence#) over(partition by thread#) a from v$archived_log;
THREAD# A
---------- ----------
1 457
SYS@dev01dg>
[oracle@testdb dev01]$ scp * [email protected]:/u01/archive/dev01dg
注册归档日志有如下两种方法,较为简单当然是用rman 了,一次注册多个。
RMAN>catalog start with '/u01/archive/dev01';
SYS@dev01dg>alter database register logfile '/u01/archive/dev01dg/arch_e8fe6364_1_712757927_460.dbf';
apply归档日志也有两种方法。
SYS@dev01dg>alter database recover managed standby database disconnect from session;
Database altered.
SYS@dev01dg>
SYS@dev01dg>recover standby database;
ORA-00279: change 2863819 generated at 03/20/2010 21:58:17 needed for thread 1
ORA-00289: suggestion : /u01/archive/dev01dg/arch_e8fe6364_1_712757927_461.dbf
ORA-00280: change 2863819 for thread 1 is in sequence #461
Specify log: {
CANCEL
Media recovery cancelled.
SYS@dev01dg>
当手动apply完所有日志后,就可以failover切换到primary了。但是要注意的时,由于备库没有收到主库End-Of-REDO的信号,所以直接转换会报错,要求介质恢复。此时需要提交命令告诉备库,日志恢复已经finish 了,需要进行failover切换。注意switchover时千万不要带有finish选项,否则就会变成failover了 。
SYS@dev01dg> alter database commit to switchover to primary with session shutdown;
alter database commit to switchover to primary with session shutdown
*
ERROR at line 1:
ORA-16139: media recovery required
SYS@dev01dg> select database_role,switchover_status from v$database;
DATABASE_ROLE SWITCHOVER_STATUS
---------------- --------------------
PHYSICAL STANDBY NOT ALLOWED
SYS@dev01dg>alter database recover managed standby database finish [force];
Database altered.
SYS@dev01dg> select database_role,switchover_status from v$database;
DATABASE_ROLE SWITCHOVER_STATUS
---------------- --------------------
PHYSICAL STANDBY TO PRIMARY
SYS@dev01dg>alter database commit to switchover to primary with session shutdown;
Database altered.
SYS@dev01dg>alter database open;
Database altered.
SYS@dev01dg> select database_role,switchover_status from v$database;
DATABASE_ROLE SWITCHOVER_STATUS
---------------- --------------------
PRIMARY SESSIONS ACTIVE
SYS@dev01dg>
failover完成后,数据库其实是以resetlogs方式打开的,如果log_archive_format='arch_%d_%t_%r_%s.dbf',可以看到归档日志的文件名会有新的resetlogs ID和sequence number,以此与原有的归档日志进行区分。