首页 » 数据库 » OCM实训:dataguard物理standby的搭建和故障切换(Oracle HA)

OCM实训:dataguard物理standby的搭建和故障切换(Oracle HA)

时间:2012-04-09作者:felix.chan分类:数据库评论:3

一、场景说明:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
1、primary server:
 
   hostname:oracle
   IP:192.168.18.1
 
primary database:
   ORACLE_SID=db1
   db_unique_name=db1
 
 
2、standby server:
 
   hostname:standby
   IP:192.168.18.2
 
standby database
   ORACLE_SID=standby
   db_unique_name=standby

要求实现standby的数据库能够和primary数据库自动同步,故障自动切换,两个物理数据库,主从数据库的名称是不同的。

二、在开始配置前,先检查服务器的主机名,ip ,hosts解析,安装好干净的数据库程序,但是不要安装数据库。

1、设置服务器名称
primary server:

1
2
3
4
5
[root@oracle ~]# cat /etc/sysconfig/network
NETWORKING=yes
NETWORKING_IPV6=no
HOSTNAME=oracle
[root@oracle ~]# hostname oracle

standby server:

1
2
3
4
5
[root@standby ~]# cat /etc/sysconfig/network
NETWORKING=yes
NETWORKING_IPV6=no
HOSTNAME=standby
[root@oracle ~]# hostname standby

2、修改本机解析配置文件:(主从服务器都需要修改)

1
2
3
4
5
6
7
[root@oracle ~]# vi /etc/hosts
# Do not remove the following line, or various programs
# that require network functionality will fail.
127.0.0.1               localhost.localdomain localhost
::1             localhost6.localdomain6 localhost6
192.168.18.1            oracle
192.168.18.2            standby

3、测试主从服务器是否可以相互ping通
在primary server上:

1
2
3
4
5
6
7
[root@oracle ~]# ping oracle
PING oracle (192.168.18.1) 56(84) bytes of data.
64 bytes from oracle (192.168.18.1): icmp_seq=1 ttl=64 time=9.76 ms
 
[root@oracle ~]# ping standby
PING standby (192.168.18.2) 56(84) bytes of data.
64 bytes from standby (192.168.18.2): icmp_seq=1 ttl=64 time=0.582 ms

在standby server上:

1
2
3
4
5
6
7
[root@standby ~]# ping oracle
PING oracle (192.168.18.1) 56(84) bytes of data.
64 bytes from oracle (192.168.18.1): icmp_seq=1 ttl=64 time=9.76 ms
 
[root@standby ~]# ping standby
PING standby (192.168.18.2) 56(84) bytes of data.
64 bytes from standby (192.168.18.2): icmp_seq=1 ttl=64 time=0.582 ms

4、配置主从服务器为相同的时区,字符集,和时间同步

1
2
3
4
5
6
7
8
9
10
11
[root@oracle ~]# env |grep LANG
LANG=en_US.UTF-8
 
[root@oracle ~]# cat /etc/sys
sysconfig/   sysctl.conf  syslog.conf
[root@oracle ~]# cat /etc/sysconfig/clock
# The ZONE parameter is only evaluated by system-config-date.
# The timezone of the system is defined by the contents of /etc/localtime.
ZONE="Asia/Shanghai"
UTC=true
ARC=false

5、关闭selinux和iptables

1
2
3
[root@oracle ~]# service iptables stop;
[root@oracle ~]# chkconfig iptables off;
[root@oracle ~]# setenforce 0

6、安装primary数据库db1

1
2
3
4
5
6
7
8
9
10
11
12
[oracle@oracle ~]$ vi .bash_profile
添加以下内容到文件末尾
 
export ORACLE_BASE=/u01/app/oracle
export ORACLE_HOME=$ORACLE_BASE/product/10.2.0/db_1
export ORACLE_SID=db1
export PATH=$PATH:$HOME/bin:$ORACLE_HOME/bin
 
xhost +
export DISPLAY=192.168.18.100:0.0
 
[oracle@oracle ~]$ dbca

执行dbca程序安装数据库

三、设置primary数据库唯一标示

1
SQL> alter system set db_unique_name='db1' scope=spfile;

四、开启primary数据库的归档日志功能 并且强制记录全部日志

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
SQL> alter database force logging;
SQL> alter system set DB_UNIQUE_NAME=oracle scope=spfile;
SQL> alter system set log_archive_config='dg_config=(db1,standby)' scope=both;
SQL> !mkdir -p /u01/archivelog;
SQL> alter system set log_archive_dest_1='location=/u01/archivelog VALID_FOR=(ALL_LOGFILES,ALL_ROLES) DB_UNIQUE_NAME=db1';
SQL> alter system set LOG_ARCHIVE_DEST_STATE_1=ENABLE;
SQL> alter system set log_archive_dest_2='SERVICE=standby LGWR ASYNC VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=standby';
SQL> alter system set LOG_ARCHIVE_DEST_STATE_2=ENABLE;
SQL> alter system set LOG_ARCHIVE_FORMAT='log%t_%s_%r.arc' scope=spfile;
SQL> alter system set REMOTE_LOGIN_PASSWORDFILE=EXCLUSIVE scope=spfile;
SQL> alter system set log_archive_start=true scope=spfile;
SQL> shutdown immediate;
SQL> startup mount;
SQL> alter database archivelog;
 
Database altered.
 
SQL> archive log list;
Database log mode              Archive Mode
Automatic archival             Enabled
Archive destination            /u01/archivelog
Oldest online log sequence     1
Next log sequence to archive   2
Current log sequence           2

五、设置数据库维护数据文件方式为自动模式:

1
SQL> alter system set STANDBY_FILE_MANAGEMENT='AUTO';

六、备份参数文件

1
SQL> create pfile from spfile;

七、生成standby用的备份控制文件

1
SQL> alter database create standby controlfile as '/u01/rmanbackup/control_standby.ctl';

八、生成primary数据库备份

1
2
3
4
5
6
7
8
9
[oracle@oracle ~]$ rman target /
connected to target database: DB1 (DBID=1373381681)
 
RMAN> host 'mkdir -p /u01/rmanbackup/';
RMAN> CONFIGURE CONTROLFILE AUTOBACKUP on;
RMAN> backup database format='/u01/rmanbackup/%d_%s.bak' plus archivelog;
 
[oracle@oracle ~]$ cd $ORACLE_BASE/flash_recovery_area
[oracle@oracle ~]$ tar zcf DB1.tar.gz  ./DB1

应为我默认的autobackup backupset onlinelog 都是放在flash_recovery_area/DB1 目录下的,如果有设置不同的目录,自己对应着打包

九、配置primary数据库监听和tnsname

1
2
3
4
5
6
7
8
9
10
[oracle@oracle rmanbackup]$ cd $ORACLE_HOME/network/admin
 
[oracle@oracle admin]$ vi listener.ora
# listener.ora Network Configuration File: /u01/app/oracle/product/10.2.0/db_1/network/admin/listener.ora
# Generated by Oracle configuration tools.
 
LISTENER =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.18.1)(PORT = 1521))
  )

重启监听:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
[oracle@oracle admin]$ lsnrctl stop
[oracle@oracle admin]$ lsnrctl start
[oracle@oracle admin]$ lsnrctl status
 
 
[oracle@oracle admin]$ vi tnsnames.ora
# tnsnames.ora Network Configuration File: /u01/app/oracle/product/10.2.0/db_1/network/admin/tnsnames.ora
# Generated by Oracle configuration tools.
 
ORACLE =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.18.1)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVICE_NAME = db1)
    )
  )
 
STANDBY =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.18.2)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVICE_NAME = standby)
    )
  )

检测tnsname配置:

1
2
3
4
5
[oracle@oracle admin]$ tnsping oracle
 
Used TNSNAMES adapter to resolve the alias
Attempting to contact (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.18.1)(PORT = 1521))) (CONNECT_DATA = (SERVICE_NAME = db1)))
OK (20 msec)

十、建立监听文件和ONS文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
[oracle@standby dbs]$ scp oracle@192.168.18.1:$ORACLE_HOME/network/admin/listener.ora $ORACLE_HOME/network/admin/
将listener.ora  文件的 HOST = 192.168.18.1  替换为  HOST = 192.168.18.2
 
[oracle@standby dbs]$ lsnrctl status
 
[oracle@standby dbs]$ scp oracle@192.168.18.1:$ORACLE_HOME/network/admin/tnsnames.ora $ORACLE_HOME/network/admin/
 
[oracle@standby dbs]$ cat $ORACLE_HOME/network/admin/tnsnames.ora
 
ORACLE =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.18.1)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVICE_NAME = db1)
    )
  )
 
STANDBY =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.18.2)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVICE_NAME = standby)
    )
  )

检查tnsname是否配置正确:

1
2
[oracle@standby dbs]$ tnsping oracle
[oracle@standby dbs]$ tnsping standby

十一、创建standby数据库

1、配置oracle环境变量:

1
2
3
4
5
6
7
8
9
10
[oracle@oracle ~]$ vi .bash_profile
添加以下内容到文件末尾
 
export ORACLE_BASE=/u01/app/oracle
export ORACLE_HOME=$ORACLE_BASE/product/10.2.0/db_1
export ORACLE_SID=standby
export PATH=$PATH:$HOME/bin:$ORACLE_HOME/bin
 
xhost +
export DISPLAY=192.168.18.100:0.0

1、建立相关目录

1
2
3
[oracle@standby app]$ mkdir -p /u01/archivelog/
[oracle@standby ~]$ mkdir -p $ORACLE_BASE/oradata/standby/
[oracle@standby ~]$ mkdir -p $ORACLE_BASE/admin/standby/{adump,bdump,udump,cdump}

2、从primary server上复制参数文件、数据文件、日志文件、控制文件、密码文件,要保证主从数据库sys密码一致

1
2
3
4
5
6
7
8
[oracle@standby dbs]$ scp oracle@192.168.18.1:$ORACLE_HOME/dbs/initdb1.ora $ORACLE_HOME/dbs/initstandby.ora
[oracle@standby dbs]$ scp oracle@192.168.18.1:$ORACLE_HOME/dbs/orapwdb1 $ORACLE_HOME/dbs/orapwstandby
[oracle@standby dbs]$ scp oracle@192.168.18.1:/u01/rmanbackup/control_standby.ctl $ORACLE_BASE/oradata/standby/control01.ctl
[oracle@standby dbs]$ scp oracle@192.168.18.1:/u01/rmanbackup/control_standby.ctl $ORACLE_BASE/oradata/standby/control02.ctl
[oracle@standby dbs]$ scp oracle@192.168.18.1:/u01/rmanbackup/control_standby.ctl $ORACLE_BASE/oradata/standby/control03.ctl
[oracle@standby dbs]$ scp oracle@192.168.18.1:$ORACLE_BASE/flash_recovery_area/DB1.tar.gz $ORACLE_BASE/flash_recovery_area/DB1.tar.gz
[oracle@standby dbs]$ cd $ORACLE_BASE/flash_recovery_area/
[oracle@standby dbs]$ tar zxf ./DB1.tar.gz

3、主从参数文件有差异的地方:

primary database:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
db1.__db_cache_size=75497472
db1.__java_pool_size=4194304
db1.__large_pool_size=4194304
db1.__shared_pool_size=75497472
db1.__streams_pool_size=0
*.audit_file_dest='/u01/app/oracle/admin/db1/adump'
*.background_dump_dest='/u01/app/oracle/admin/db1/bdump'
*.control_files='/u01/app/oracle/oradata/db1/control01.ctl','/u01/app/oracle/oradata/db1/control02.ctl','/u01/app/oracle/oradata/db1/control03.ctl'
*.core_dump_dest='/u01/app/oracle/admin/db1/cdump'
*.db_unique_name='db1'
*.dispatchers='(PROTOCOL=TCP) (SERVICE=db1XDB)'
*.log_archive_dest_1='location=/u01/archivelog VALID_FOR=(ALL_LOGFILES,ALL_ROLES) DB_UNIQUE_NAME=db1'
*.log_archive_dest_2='SERVICE=standby LGWR ASYNC VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=standby'
*.user_dump_dest='/u01/app/oracle/admin/db1/udump'
FAL_SERVER='db1'
FAL_CLIENT='standby'
DB_FILE_NAME_CONVERT='oradata/standby','oradata/db1'
LOG_FILE_NAME_CONVERT='oradata/standby','oradata/db1'

#说明:
#primary和standby上的db_name都是一致的,用DB_UNIQUE_NAME来区分多实例环境。
#FAL_SERVER=’db1′ FAL_SERVER=本机数据库的DB_UNIQUE_NAME
#FAL_CLIENT=’standby’ FAL_CLIENT=对方数据库的DB_UNIQUE_NAME
#log_archive_dest_2=’SERVICE=standby LGWR ASYNC VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=standby’
#SERVICE=standby 这个standby为tnsname中配置的standby dg的名字,要用tnsping standby可以通过才行,DB_UNIQUE_NAME=standby 这个standby为standby数据库的参数文件中配置的名字。

standby database:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
standby.__db_cache_size=75497472
standby.__java_pool_size=4194304
standby.__large_pool_size=4194304
standby.__shared_pool_size=75497472
standby.__streams_pool_size=0
*.audit_file_dest='/u01/app/oracle/admin/standby/adump'
*.background_dump_dest='/u01/app/oracle/admin/standby/bdump'
*.control_files='/u01/app/oracle/oradata/standby/control01.ctl','/u01/app/oracle/oradata/standby/control02.ctl','/u01/app/oracle/oradata/standby/control03.ctl'
*.core_dump_dest='/u01/app/oracle/admin/standby/cdump'
*.db_unique_name='standby'
*.dispatchers='(PROTOCOL=TCP) (SERVICE=standbyXDB)'
*.log_archive_dest_1='location=/u01/archivelog VALID_FOR=(ALL_LOGFILES,ALL_ROLES) DB_UNIQUE_NAME=standby'
*.log_archive_dest_2='SERVICE=oracle LGWR ASYNC VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=db1'
*.user_dump_dest='/u01/app/oracle/admin/standby/udump'
FAL_SERVER='standby'
FAL_CLIENT='db1'
DB_FILE_NAME_CONVERT='oradata/db1','oradata/standby'
LOG_FILE_NAME_CONVERT='oradata/db1','oradata/standby'

#说明:
#primary和standby上的db_name都是相同的,用DB_UNIQUE_NAME来区分多实例环境。
#FAL_SERVER=’standby’ FAL_SERVER=本机数据库的DB_UNIQUE_NAME
#FAL_CLIENT=’db1′ FAL_CLIENT=对方数据库的DB_UNIQUE_NAME
#log_archive_dest_2=’SERVICE=oracle LGWR ASYNC VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=db1′
#SERVICE=oracle 这个oracle为tnsname中配置的primary dg的名字,要用tnsping oracle可以通过才行,DB_UNIQUE_NAME=db1 这个db1为primary数据库的参数文件中配置的名字。

4、将standby数据库启动到mount状态

1
2
3
[oracle@standby dbs]$ sqlplus / as sysdba;
SQL> startup nomount;
SQL> alter database mount standby database;

5、使用rman恢复数据库

1
RMAN> restore database;

6、启动redo应用

1
SQL> alter database recover managed standby database disconnect from session;

7、#如果有需要应用的日志并想手工应用,可以运行如下命令

1
SQL> recover automatic standby database;

8、测试data guard是否能够正常同步

在primary database中:

1
2
3
4
5
6
SQL>  alter system switch logfile;
SQL> select max(sequence#) from v$archived_log;
 
MAX(SEQUENCE#)
--------------
            13

在standby database中:

1
2
3
4
5
6
7
8
9
10
11
12
SQL> select sequence# ,applied from v$archived_log order by sequence#;
 
 SEQUENCE# APP
---------- ---
         8 YES
         9 YES
        10 YES
        11 YES
        12 YES
        13 YES
 
6 rows selected.

可以看到primary 和 standby的redo log sn是一致的。

9、测试一切都正常,就将standby数据库创建spfile并且启动

1
2
3
4
5
SQL> create spfile from pfile;
SQL> shutdown abort;
SQL> startup mount;
SQL> alter database recover managed standby database disconnect from session;
SQL> recover automatic standby database;

暂停standby数据库的日志应用:

1
SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL;

十二、dataguard的角色转换

1、switchover

当primary 数据库是正常工作的,但是需要进行down机维护的时候,可以switchover

db1: 原来为primary 切换后变为standby
standby:原来为standby 切换后变为primary

第一步,将primary(sid=db1)数据库转换为standby角色

1
2
3
4
5
6
7
8
9
10
11
SQL> select switchover_status from v$database;
 
SWITCHOVER_STATUS
--------------------
SESSIONS ACTIVE
 
SQL> alter database commit to switchover to physical standby with session shutdown ;
SQL> shutdown immediate;
SQL> startup mount;
SQL> alter database recover managed standby database disconnect from session;
SQL> recover automatic standby database;

switchover_status的值入股是To standby,可以直接switchover,如果是sessions active,则需要在switchover的命令后面加上with session shutdown

第二布,将standby(sid=standby)数据库转换为primary角色

1
2
3
4
5
6
7
8
9
SQL> select switchover_status from v$database;
 
SWITCHOVER_STATUS
--------------------
TO PRIMARY
 
SQL> alter database commit to switchover to primary;
SQL> shutdown immediate;
SQL> startup

switchover_status的值入股是To primary,可以直接switchover,如果是sessions active,则需要在switchover的命令后面加上with session shutdown;

第三步,检查primary(sid=standby) 和standby(sid=db1) 数据库是否同步

在primary(standby)数据库中创建一个新表插入数据,并且查看当前log的序列号:

1
2
3
4
5
6
7
8
9
10
SQL> create table t (name char(10),id number);
SQL> insert into t values('felix.chan',1);
SQL> insert into t values('rednat.com',2);
SQL> commit;
SQL> alter system switch logfile;
SQL> select max(sequence#) from v$archived_log;
 
MAX(SEQUENCE#)
--------------
            27

在standby(sid=db1)数据库中检查结果,看看standby(sid=db1)中是否可以同步过去,并且检查log的序列号是否一致:
物理dg在open之前必须停止应用log备份

1
2
3
4
5
6
7
8
9
SQL> select max(sequence#) from v$archived_log;
SQL> alter database recover managed standby database cancel;
SQL> alter database open read only;
SQL> select * from t;
 
NAME               ID
---------- ----------
felix.chan          1
rednat.com          2

如果可以看到我刚才创建的表和插入的记录,说明已经成功了,在将现在的standby(sid=db1) 数据库启动到应用log备份状态:

1
SQL> alter database recover managed standby database disconnect from session;

如果在primary 和 standby 上的序列号一致则是正常的;不一致则需要查看alert.log文件中是否想error

2、failover

当primary 数据库出现故障无法启动,或是服务器出现硬件故障,而且无法在短时间内修复,需要failover

当primary出现突发性故障而无法启动是,有可能primary上的部事务没有传送到standby上,所以可能存在数据丢失的可能

这个时候primary服务器上不用在做什么操作了,主要是先将standby服务器正常运营起来:

a、检查归档日志是否连续,在standby(sid=db1)上进行一下操作:

1
2
3
SQL> SELECT THREAD#, LOW_SEQUENCE#, HIGH_SEQUENCE# FROM V$ARCHIVE_GAP;
 
no rows selected

可以看到是没有记录的,说明归档文件都已经从primary(sid=standby)上复制到本机了,那就没有问题了。
如果有记录,则需要根据记录将指定的归档日志从primary(sid=standby)服务器上复制到standby(sid=db1)上,
然后在通过下面的命令将归档日志加入到数据字典中:

1
SQL> ALTER DATABASE REGISTER PHYSICAL LOGFILE 'filespec1';

b、检查归档文件是否完整:

1
2
3
4
5
SQL> select distinct thread#,max(sequence#) over(partition by thread#) a from v$archived_log;
 
   THREAD#          A
---------- ----------
         1         29

可以看到我查出来的归档文件的序列号是29,如果primary上和standby上的归档目录中文件序号和这个一致,则说明是完整的。
如果不完整,可能无法还原到最近的时间点,只能做不一致性恢复了。那就要丢数据咯。。。。

c、立刻执行failover,将standby切换成primary

1
2
3
4
5
6
7
8
SQL> alter database recover managed standby database finish force;
#FORCE 关键字将会停止当前活动的RFS 进程,以便立刻执行failover。
 
SQL> alter database recover managed standby database finish force;
 
SQL> shutdown immediate;
 
SQL> startup;

剩下的工作就是修复原来故障服务器后再重新加入到dg中:

方法一:重新建库,然后在加入到dg中
方法二:通过备份,键入到dg中,做standby库使用。

原创文章,转载请注明: 转载自红防联盟www.rednat.com

本文链接地址: OCM实训:dataguard物理standby的搭建和故障切换(Oracle HA)

|2|right
3 条评论
  1. avatar
    ymh China Internet Explorer Windows 2012-04-20 22:17 回复

    看看

  2. avatar
    aka China Internet Explorer Windows 2012-05-12 22:11 回复

    学习

  3. avatar
    aka China Internet Explorer Windows 2012-05-12 22:18 回复

    期待关于ocm的更多内容

发表评论

电子邮件地址不会被公开。 必填项已用 * 标注

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>