一、Data Guard提供如下三种数据保护模式:

1)最高保护模式(Maximum Protection)

这里的”最高保护“是指最大限度的保护数据不丢失,也就是至少有一个standby和primary保持实时同步,但这样做的代价很大,因为只要当一个事务提交时,不但要写到primary段的online redo log,还有写到至少一个standby的standby redo log。这样会有一个严重的问题,就是当standby出现故障或网络故障,导致日志无法同步时,primary数据库会被shutdown,这在生产系统中是不可接受的,因此这种模式很少用。

2)最高性能模式(Maximum Performance)

最高性能正好和最高保护相反,当事务提交时,只要写入到primary的online redo log即可,primary几乎不受影响。然后再把redo同步到standby中,这样就无法保证primary和standby实时同步。这种模式在实际应用中比较常见,毕竟primary不受影响是最重要的,如果出现standby落后primary太多,DBA可以手工介入,在standby端apply redo。

3)最高可用性模式(Maximum Availability)

最高可用性模式介于前两者之间,在正常情况下,它和最高保护模式一样,但一旦standby出现故障,就立即切换成最高性能模式,primary不会shutdown。如果实际应用该模式,得关注一下实时应用时对primary的性能影响。

那么如何配置及修改DG的保护模式呢?首先你要检查以下2点:

1. 主备库的db_unique_name是否唯一?

2. log_archive_config的dg_config属性是否已经包含所有的主备库db_unique_name?

以上2点确认之后,就可以使用LOG_ARCHIVE_DEST_n来配置,下表显示该参数和保护模式的关系:

(转)Oracle Data Guard学习-LMLPHP

从上图可以看出,最大保护和最高可用性的配置一模一样(这很正常因为最高可用性在正常情况下就是最大保护):必须使用LGWR进程传输Redo,网络传输模式必须是sync,磁盘写选项AFFIRM,必须配置standby redo log。

而最大性能模式比较灵活,即可以用LGWR,也可以用ARCH进程传输redo,网络即可以sync也可以async,磁盘IO写即可以AFFIRM也可以NOAFFIRM,standby redo log也可有可无(建议有)。

上面所有的参数都确认配置无误之后,就可以用以下语句修改保护模式:

  1. ALTER DATABASE SET STANDBY DATABASE TO MAXIMIZE {AVAILABILITY | PERFORMANCE | PROTECTION};

修改成功后,可以通过以下语句验证:

  1. SELECT PROTECTION_MODE FROM V$DATABASE;

二、日志传输

Oracle Data Guard从宏观上来说,主要提供以下两个服务:

1)日志传输:主库把生成的Redo日志传输至备库;

2)日志应用:备库应用从主库传输过来的Redo日志。

1. 日志传输方式

有两种日志传输方式(ARC和LGWR),第一种是采用ARC进程传输日志,其示意图如下:

(转)Oracle Data Guard学习-LMLPHP

注:上图来自《大话Oracle RAC》

其大致过程如下:

1)主库:日志先写入在线重做日志,当在线重做日志满后(后人为切换), ARC0进程归档该日志至主库本地归档目录,归档完成后,ARC1马上将该归档日志传输到备库;

2)备库:RFS进程接收日志,如果备库有Standby重做日志,则把日志复制到Standby重做日志,接着把Standby重做日志归档至备库本地归档目录,最后应用归档日志;如果没有配置Standby重做日志,RFS进程接收日志后,直接把它放到备库的归档目录下,再应用该日志。

另外一种是使用LGWR进程传输日志,它和第一种方式有很大的不同,最明显的区别是它不需要等到主库完成日志切换后才能进行日志传输,其示意图如下:

(转)Oracle Data Guard学习-LMLPHP

注:上图来自《大话Oracle RAC》

其过程大致如下:

1)主库:只要有新的重做日志产生,LGWR进程将触发LNSn进程把新生成的日志传输到备库(注意:这里不能由LGWR直接传输,因为整个数据库实例只有一个LGWR,为了保证它的主要业务性能不受影响,不能由它直接传输);

2)备库:RFS进程接收到日志后,将其写入Standby重做日志,如果备库开启了实时应用,就立即做日志应用,如果没有开启,则等Standby重做日志归档后再应用。

2.日志发送的配置

主库的日志发送是由log_archive_dest_n参数设置(注意:同时还有一个和它相对应的开关参数log_archive_dest_state_n,用于指定该参数是否有效),下面简单介绍下该参数各个属性的含义。

SERVICE(必须):指定备库的网络连接名;

SYNC/ASYNC(默认为ASYNC):指定日志的传输模式(同步/异步);

NET_TIMEOUT:指定当采用SYNC传输模式时,超过多少秒则表示网路超时(默认为30s),在使用SNYC模式时,强烈建议设置改参数;

AFFIRM/NOAFFIRM:AFFIRM表示只有当日志写入Standby重做日志后才算日志传输成功,NOAFFIRM则没有这个要求;

DB_UNIQUE_NAME:指定备库的DB_UNIQUE_NAME;

VALID_FOR:格式为(redo_log_type,database_role),只有这两个条件全部符合,才会发送日志;

 其中redo_log_type有如下取值:ONLINE_LOGFILE, STANDBY_LOGFILE, ALL_LOGFILES

database_role有如下取值:PRIMARY_ROLE, STANDBY_ROLE, ALL_ROLES

REOPEN:指定当连接错误发生时,多少秒之后重试;

COMPRESSION:指定是否对日志进行压缩,已提高网络传输性能。

下面是log_archive_dest_n的一个例子:

DB_UNIQUE_NAME=BOSTON
LOG_ARCHIVE_CONFIG='DG_CONFIG=(BOSTON,CHICAGO,HARTFORD)'
LOG_ARCHIVE_DEST_2='SERVICE=CHICAGO ASYNC NOAFFIRM VALID_FOR=(ONLINE_LOGFILE,
PRIMARY_ROLE) REOPEN=60 COMPRESSION=ENABLE DB_UNIQUE_NAME=CHICAGO'
LOG_ARCHIVE_DEST_STATE_2='ENABLE'
LOG_ARCHIVE_DEST_3='SERVICE=HARTFORD SYNC AFFIRM NET_TIMEOUT=30
VALID_FOR=(ONLINE_LOGFILE,PRIMARY_ROLE) REOPEN=60 COMPRESSION=ENABLE
DB_UNIQUE_NAME=HARTFORD'
LOG_ARCHIVE_DEST_STATE_3='ENABLE'

3.日志接受的配置

在备库,当RFS进程接受到日志后,就将其写入Standby日志文件里,备库的Standby日志文件可以看做是主库在线日志文件的一个镜像,当主库做日志切换时,备库的Standby日志也做相应的切换,切换后的Standby日志由备库的ARCH进程归档。
 Oracle规定备库的Standby日志文件大小不能小于主库在线日志文件最大的一个,一般情况下,为了管理方便,最好把所有的在线日志和Standby日志大小设为一样。
Oracle还规定备库的Standby日志文件至少要比主库的在线日志文件多一组。
通过下面语句可以查询主库在线日志的大小和组数:
SQL> SELECT GROUP#, BYTES FROM V$LOG;

通过下面的语句可以查询备库Standby日志的大小和组数:

SQL> SELECT GROUP#, BYTES FROM V$STANDBY_LOG;

假设主库有两组在线日志,每个日志文件大小为500M,那么我们至少需要3组Standby,且每个日志文件大小不少于500M:

SQL> ALTER DATABASE ADD STANDBY LOGFILE ('/oracle/dbs/slog1.rdo') SIZE 500M;
SQL> ALTER DATABASE ADD STANDBY LOGFILE ('/oracle/dbs/slog2.rdo') SIZE 500M;
SQL> ALTER DATABASE ADD STANDBY LOGFILE ('/oracle/dbs/slog3.rdo') SIZE 500M;

上面提到过,备库的Standby日志也会被归档,它的归档路径由备库的log_archive_dest_n参数的location属性设置,如下所示:

LOG_ARCHIVE_DEST_1 = 'LOCATION = /disk2/archive
VALID_FOR=(STANDBY_LOGFILE,STANDBY_ROLE)'
LOG_ARCHIVE_DEST_STATE_2=ENABLE

4.日志传输状态的监控

第一步:在主库执行如下语句获得最新归档序列号:

SQL> SELECT MAX(SEQUENCE#), THREAD# FROM V$ARCHIVED_LOG GROUP BY THREAD#;

第二步:在主库执行如下语句确认最新归档的日志是否已经传输至备库:

SQL> SELECT DESTINATION, STATUS, ARCHIVED_THREAD#, ARCHIVED_SEQ# FROM V$ARCHIVE_DEST_STATUS  WHERE STATUS <> 'DEFERRED' AND STATUS <> 'INACTIVE';

DESTINATION         STATUS  ARCHIVED_THREAD#  ARCHIVED_SEQ#
------------------ ------ ---------------- -------------
/private1/prmy/lad VALID 1 947
standby1 VALID 1 947 如果状态不是VALID,则说明日志传输失败。
5.手动解决日志传输GAP

Oracle DG会自动检测日志传输GAP并自动解决,但有时候GAP无法自动解决,必须DBA人工干预,下面我们讲讲手动解决的步骤:

首先,在备库执行下列语句查询是否有GAP:

SQL> SELECT * FROM V$ARCHIVE_GAP;

    THREAD# LOW_SEQUENCE# HIGH_SEQUENCE#
----------- ------------- --------------
1 7 10

HIGH_SEQUENCE#减去LOW_SEQUENCE#就是当前的GAP数,上例显示备库缺少从7到10(不包含10)的归档日志。

接着,在主库查询这些归档日志的目录位置:

SQL> SELECT NAME FROM V$ARCHIVED_LOG WHERE THREAD#=1 AND DEST_ID=1 AND SEQUENCE# BETWEEN 7 AND 10;
NAME
--------------------------------------------------------------------------------
/primary/thread1_dest/arcr_1_7.arc
/primary/thread1_dest/arcr_1_8.arc
/primary/thread1_dest/arcr_1_9.arc

把这些归档日志从主库拷贝至备库,并在备库上注册:

SQL> ALTER DATABASE REGISTER LOGFILE '/physical_standby1/thread1_dest/arcr_1_7.arc';

SQL> ALTER DATABASE REGISTER LOGFILE '/physical_standby1/thread1_dest/arcr_1_8.arc';

SQL> ALTER DATABASE REGISTER LOGFILE '/physical_standby1/thread1_dest/arcr_1_9.arc';

三、日志应用

在上一节,我们介绍了DG的日志传输服务,当日志从主库传输至备库后,备库需要应用日志来保持和主库的同步,本节就来介绍日志应用服务。

 Redo应用orSQl应用

我们知道有两种类型的备库,分别是物理备库和逻辑备库,物理备库的日志应用叫做Redo应用,而逻辑备库的日志应用叫做SQL应用。

所谓的Redo应用是指备库采用介质恢复的方式应用主库传输过来的日志,因此物理备库就像是主库的一面镜子,不但数据一样,物理结构(如数据块、数据文件等)都一样,这样的好处是同步速度快。

所谓的SQL应用是指备库通过Log Miner从日志中解析出SQL语句,然后应用这些SQL语句,很显然,SQL应用的性能比不上Redo应用,但它更灵活。逻辑备库采用SQL应用。

 实时日志应用

 默认情况下,只有等Standby日志文件归档后才进行日志应用,如果你想一接收到从主库传输过来的日志,马上进行日志应用,则必须打开实时应用,这样只要RFS进程接收到日志并写入Standby日志文件后,MRP/LSP 进程能在备库第一时间应用日志,从而实现主备库的实时同步。
  1. 物理备库通过以下语句开启实时应用:
  2. SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE USING CURRENT LOGFILE ;
  3. 逻辑备库通过以下语句开启实时应用:
  4. SQL> ALTER DATABASE START LOGICAL STANDBYAPPLY IMMEDIATE;

 开启/关闭日志应用服务

物理备库:

  1. --开启
  2. SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DISCONNECT;
  3. --关闭
  4. SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL;

逻辑备库:

  1. --开启
  2. SQL> ALTER DATABASE START LOGICAL STANDBY APPLY;
  3. --关闭
  4. SQL> ALTER DATABASE STOP LOGICAL STANDBY APPLY;

四、在不停主库的情况下创建物理备库

今天需要对一个24*7的生产库创建一个DG的物理备库,要求主库不能停机,一开始以为不可能,后来查了下文档,原来通过rman的duplicate命令可以实现在线创建物理备库。

主备库的信息如下:

角色      db_name      db_unique_name      主机           网络连接字符串

主库       jkka                jkka                            lx32            jkkapri

备库       jkka                jkka2                          lx201         jkkasta

1.主库的准备工作

 1)确认主库已开启归档和force logging
DG要求主库一定要开启归档和force logging,可以通过以下语句查询:
  1. SYS@JKKA>select log_mode,force_logging from v$database;
  2. LOG_MODE     FOCE_LOGGING
  3. ARCHIVELOG   NO

从上面我们发现主库已经开启了归档,但没有开启force logging,可以通过以下语句开启:

SYS@JKKA>alter database force logging;  
                  Database altered.  
2)创建主库密码文件
主备库间需要通过密码文件互相通讯,我们先在主库端创建密码文件,之后再把它同步到备库中:
  1. $ orapwd file=$ORACLE_HOME/dbs/orapwjkka

确认参数remote_login_passwordfile为EXCLUSIVE(默认值):

  1. SYS@JKKA>show parameter remote_login_passwordfile
  2. NAME                                            TYPE        VALUE
  3. remote_login_passwordfile            string      EXCLUSIVE

通过v$pwfile_users再次确认sys用户在密码文件中:

SYS@JKKA>select * from v$pwfile_users;  
USERNAME                  SYSDB SYSOP SYSAS  
SYS                            TRUE  TRUE  FALSE  
 3)配置主库参数
首先,查看主库的db_name和db_unique_name:
  1. NAME                                 TYPE        VALUE
  2. db_name                              string      jkka
  3. SYS@JKKA>show parameter db_unique_name
  4. NAME                                 TYPE        VALUE
  5. db_unique_name                  string      jkka

接着,修改log_acchive_config参数,在dg_config属性分别写上主备库的db_unique_name:

  1. SYS@JKKA>alter system set log_archive_config='DG_CONFIG=(jkka,jkka2)';
  2. System altered.

配置log_archive_dest_1写入本地目录:

  1. SYS@JKKA>alter system set log_archive_dest_1='location=/data/oradata/jkka/archivelog  valid_for=(all_logfiles,all_roles) db_unique_name=jkka';
  2. System altered.
  3. SYS@JKKA>alter system set log_archive_dest_state_1=enable;
  4. System altered.
配置log_archive_dest_2写入远程目录,因为这时候还没有备库,所有这里我们暂时把log_archive_dest_state_2设为defer:
  1. SYS@JKKA>alter system set log_archive_dest_state_2=defer;
  2. System altered.
  3. SYS@JKKA>alter system set log_archive_dest_2='service=jkkasta ASYNC VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) db_unique_name=jkka2';
  4. System altered.

下面这些参数是可选的,只有当主库切换成备库时有效,但强烈建议配置,否则以后主备库切换会失败。

  1. SYS@JKKA>alter system set fal_server=jkka2;
  2. System altered.
  3. SYS@JKKA>alter system set fal_client=jkka;
  4. System altered.
  5. SYS@JKKA>alter system set standby_file_management=auto;
  6. System altered.

最后创建pfile

  1. SYS@JKKA>create pfile from spfile;
  2. File created.
 2.启动备库实例
1)安装数据库软件
安装Oracle软件这里就不再累述,要注意的一点是备库的版本要和主库的一样。(注意:这里的版本包括小版本也要一样,比如主库是11.2.0.1,备库时11.2.0.3就不行)
2)创建备库的参数文件
备库的参数文件可以根据主库的参数文件适当修改即可,在之前我们已经生成了主库的pfile,所有我们只要把它拷贝到备库,然后修改以下参数:
  1. db_unique_name='jkka2'
  2. fal_client='JKKA2'
  3. fal_server='JKKA'
  4. log_archive_dest_1='location=/data/oradata/jkka/archivelog  valid_for=(all_logfiles,all_roles) db_unique_name=jkka2'
  5. log_archive_dest_2='service=jkkapri ASYNC VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) db_unique_name=jkka'
3)拷贝主库的密码文件至备库

4)在备库上创建和主库一模一样的目录结构

需要创建的目录有日志文件、控制文件、数据文件、归档日志、audit目录等。
5)启动备库至nomount状态
  1. $ export ORACLE_SID=jkka
  2. $ sqlplus / as sysdba
  3. SQL>startup nomount
  4. 主备库的网络设置

1)主库的监听器设置

  1. LISTENER =
  2. (DESCRIPTION_LIST =
  3. (DESCRIPTION =
  4. (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521))
  5. (ADDRESS = (PROTOCOL = TCP)(HOST = lx32)(PORT = 1521))
  6. )
  7. )

2)备库的监听器设置

  1. LISTENER =
  2. (DESCRIPTION_LIST =
  3. (DESCRIPTION =
  4. (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521))
  5. (ADDRESS = (PROTOCOL = TCP)(HOST = lx201)(PORT = 1521))
  6. )
  7. )

3)主备库tnsnames.ora的设置

  1. jkkasta =
  2. (DESCRIPTION =
  3. (ADDRESS_LIST =
  4. (ADDRESS = (PROTOCOL = TCP)(HOST =lx201)(PORT = 1521))
  5. )
  6. (CONNECT_DATA =
  7. (sid = jkka)
  8. )
  9. )
  10. jkkapri =
  11. (DESCRIPTION =
  12. (ADDRESS = (PROTOCOL = TCP)(HOST =lx32)(PORT = 1521))
  13. (CONNECT_DATA =
  14. (SERVER = DEDICATED)
  15. (sid =jkka)
  16. )
  17. )

4)测试主备库是否互通

因为之前在主备库上都已经有了密码文件,所有可以使用sys用户远程登录来测试:
  1. 主库:
  2. $ sqlplus sys@jkkasta as sysdba
  3. 备库:
  4. $ sqlplus sys@jkkapri as sysdba

5)复制主库到备库

我们可以通过rman的duplicate命令,在主库不停机的情况下,创建备库。这里有个前提条件,就是备库的目录结构和主库一模一样。
1)创建主库备份
备份全库和归档日志:
  1. $ rman target /
  2. RMAN> backup full format='/home/oracle/backup/ora_bak/data/db_jkka_%U' database include current controlfile for standby
  3. plus archivelog format='/home/oracle/backup/ora_bak/data/arc_jkka_%U';
备份成功后,手动把备份文件拷贝至备库主机(scp,ftp等)。
2)在备库执行恢复
在执行恢复之前,一定要保证三点:1,备份文件在备库的目录一定要和主库的一样;2,备库存放数据文件等相应的目录都已存在。3,备库处于nomount状态
  1. $ rman target sys/***@jkkapri AUXILIARY /
  2. RMAN> duplicate target database for standby dorecover nofilenamecheck;
上面的语句执行完毕后,会在相应目录下生成数据文件、日志文件、audit,数据库处于mount状态。
有可能会出现下面的错误:
  1. ORACLE error from auxiliary database: ORA-19527: physical standby redo log must be renamed
  2. ORA-00312: online log 1 thread 1: '/data/oradata/jkka/data/redoa1.log'
  3. RMAN-05535: WARNING: All redo log files were not defined properly.

这是因为oracle为了加快备库与主库switchover的速度,从10.2开始增加了一个增强的功能,就是当MRP启动时会去清理备库上online redo log。如果不考虑switchover(备库上不创建online reod log),那么可以忽略这个错误,因为这个错只是一个提示性的信息,不会影响备库的MRP的工作。如果考虑switchover,就要在备库上创建online reod log,需要数据库在打开的情况下,具体见第5)步。

 
3)在主备库上分别创建standby redo log
Oracle规定standby redo log的大小不得小于online redo log
  1. SYS@JKKA>ALTER DATABASE ADD STANDBY LOGFILE GROUP 10 ('/data/oradata/jkka/data/standby_redo10.log') size 100M
  2. Database altered.
  3. SYS@JKKA>ALTER DATABASE ADD STANDBY LOGFILE GROUP 11 ('/data/oradata/jkka/data/standby_redo11.log') size 100M;
  4. Database altered.
  5. SYS@JKKA>ALTER DATABASE ADD STANDBY LOGFILE GROUP 12 ('/data/oradata/jkka/data/standby_redo12.log') size 100M;
  6. Database altered.
  7. SYS@JKKA>ALTER DATABASE ADD STANDBY LOGFILE GROUP 13 ('/data/oradata/jkka/data/standby_redo13.log') size 100M;
  8. Database altered.
4)创建备库的spfile,重启备库至mount或open状态
从11g开始,物理备库既可以启动至moutn,也可以启动至open
  1. SQL>create spfile from pfile;
  2. File created.
  3. SQL>shutdown immediate
  4. SQL>startup

五、重建备库的online redo log

SYS@jkka> alter system set standby_file_management=manual;

System altered.  SYS@jkka> alter system set LOG_FILE_NAME_CONVERT='/data/oradata/jkka/data/','/data/oradata/jkka/data/' scope=spfile;

System altered.

shutdown immediate;

startup;

SYS@jkka> alter database clear logfile group 1;

Database altered.  
SYS@jkka> alter database clear logfile group 2;

Database altered.

SYS@jkka> alter database clear logfile group 3;

Database altered.

SYS@jkka> alter system reset LOG_FILE_NAME_CONVERT;

System altered.

shutdown immediate;

startup;

SYS@jkka> alter system set standby_file_management=auto;

System altered.

六)备库启动redo apply

因为之前我们把log_archive_dest_state_2设为defer,现在需要在主备库中把它设为enable:

System altered.

现在一切都已准备就绪,可以在备库启动日志应用:

下面验证主备库间是否可以同步,首先查看备库当前的归档日志:

SQL>SELECT SEQUENCE#, FIRST_TIME, NEXT_TIME FROM V$ARCHIVED_LOG ORDER BY SEQUENCE#;  SEQUENCE# FIRST_TIME          NEXT_TIME  

504 2013-08-22 14:41:54 2013-08-22 20:32:39

从上面我们可以看出备库当前最大的归档日志为504。
然后再查看主库当前最大的归档日志也是504:
SYS@JKKA>select max(sequence#) from v$archived_log;  
MAX(SEQUENCE#)
 504  

我们在主库做一次日志切换,此时主库的最大归档日志为505.

SYS@JKKA>ALTER SYSTEM SWITCH LOGFILE;  
System altered.  

这时再看备库的归档日志,如果505已经从主库成功拷贝至备库,说明主备库同步正常。

04-30 00:41