Switchover是将主从库角色切换,无损转换,通常是用户手动触发或者有计划的让其自动触发,比如硬件升级啦,软件升级啦之类的。而failover是当主库发生故障时,如何将从库切换成主库。

一、如何使用sql命令进行switchover 。

  1. 检查主库是否支持switchover操作

登录数据库,执行如下查询

SQL> select switchover_status from v$database;

SWITCHOVER_STATUS
------------------------------------------------------------
TO STANDBY

如果该列值为"TO STANDBY"则表示primary 数据库支持转换为standby 角色。


2.将主库切换成备库

SQL> ALTER DATABASE COMMIT TO SWITCHOVER TO PHYSICAL STANDBY;


Database altered.


3.将主库关闭,再启动到mount状态

SQL> shutdown immediate
ORA-01092: ORACLE instance terminated. Disconnection forced
SQL> conn / as sysdba
Connected to an idle instance.
SQL> startup mount
ORACLE instance started.

Total System Global Area  839282688 bytes
Fixed Size		    2233000 bytes
Variable Size		  499125592 bytes
Database Buffers	  335544320 bytes
Redo Buffers		    2379776 bytes
Database mounted.

4.检查从库是否支持switchover 操作

SQL> select switchover_status from v$database;

SWITCHOVER_STATUS
------------------------------------------------------------
SESSIONS ACTIVE

表示还有活动的会话连接该数据库。将数据库关闭,并重启到mount状态。

SQL> STARTUP MOUNT;
ORACLE instance started.

Total System Global Area  839282688 bytes
Fixed Size		    2233000 bytes
Variable Size		  494931288 bytes
Database Buffers	  339738624 bytes
Redo Buffers		    2379776 bytes
Database mounted.
SQL> select switchover_status from v$database;

SWITCHOVER_STATUS
------------------------------------------------------------
TO PRIMARY

5. 执行switchover操作

SQL> alter database commit to switchover to primary;

Database altered.
SQL> alter database open;

Database altered.

也可以使用新语法,切换时关闭session

ALTER DATABASE COMMIT TO SWITCHOVER TO PHYSICAL STANDBY WITH SESSION SHUTDOWN;

6. 将新的从库打开到只读。

SQL>  select switchover_status from v$database;

SWITCHOVER_STATUS
------------------------------------------------------------
RECOVERY NEEDED

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

Database altered.

SQL>  select switchover_status from v$database;

SWITCHOVER_STATUS
------------------------------------------------------------
NOT ALLOWED

SQL> alter database open read only;

Database altered.


二、使用Broker进行switchover。

特别注意:一旦配置了Broker,就不要再用sqlplus去管理DataGuard。否则Broker将出现问题。

执行完sql的switchover后,Broker报如下错误。

DGMGRL> show configuration;

Configuration - dr1

  Protection Mode: MaxAvailability
  Databases:
    11gdg2 - Primary database
      Error: ORA-16816: incorrect database role

    11gdg1 - Physical standby database
      Error: ORA-16810: multiple errors or warnings detected for the database

Fast-Start Failover: DISABLED

Configuration Status:
ERROR

DGMGRL> show database verbose 11gdg2;

Database - 11gdg2

  Role:            PRIMARY
  Intended State:  TRANSPORT-ON
  Instance(s):
    dgtst

  Database Error(s):
    ORA-16816: incorrect database role

  Properties:
    DGConnectIdentifier             = '11gdg2'
    ObserverConnectIdentifier       = ''
    LogXptMode                      = 'SYNC'
    DelayMins                       = '0'
    Binding                         = 'OPTIONAL'
    MaxFailure                      = '0'
    MaxConnections                  = '1'
    ReopenSecs                      = '300'
    NetTimeout                      = '30'
    RedoCompression                 = 'DISABLE'
    LogShipping                     = 'ON'
    PreferredApplyInstance          = ''
    ApplyInstanceTimeout            = '0'
    ApplyParallel                   = 'AUTO'
    StandbyFileManagement           = 'AUTO'
    ArchiveLagTarget                = '0'
    LogArchiveMaxProcesses          = '4'
    LogArchiveMinSucceedDest        = '1'
    DbFileNameConvert               = ''
    LogFileNameConvert              = ''
    FastStartFailoverTarget         = ''
    InconsistentProperties          = '(monitor)'
    InconsistentLogXptProps         = '(monitor)'
    SendQEntries                    = '(monitor)'
    LogXptStatus                    = '(monitor)'
    RecvQEntries                    = '(monitor)'
    SidName                         = 'dgtst'
    StaticConnectIdentifier         = '(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=11gdg2.localdomain.com)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=11gdg2_DGMGRL)(INSTANCE_NAME=dgtst)(SERVER=DEDICATED)))'
    StandbyArchiveLocation          = 'USE_DB_RECOVERY_FILE_DEST'
    AlternateLocation               = ''
    LogArchiveTrace                 = '0'
    LogArchiveFormat                = '%t_%s_%r.dbf'
    TopWaitEvents                   = '(monitor)'

Database Status:
ERROR

Broker中Primary还是11gdg2呢~ 信息不一致啦。只能重新配置Broker啦。

DGMGRL> REMOVE CONFIGURATION  PRESERVE DESTINATIONS;
Removed configuration

...重新配置完毕,执行如下语句进行switchover。

DGMGRL> DGMGRL> 11gdg1-> dgmgrl
DGMGRL for Linux: Version 11.2.0.3.0 - 64bit Production

Copyright (c) 2000, 2009, Oracle. All rights reserved.

Welcome to DGMGRL, type "help" for information.
DGMGRL> CONNECT sys/oracle@11gdg1
Password:
Connected.
DGMGRL> SWITCHOVER TO 11gdg2;

三、模拟故障,实现failover 。

注意几点:

  • failover 之后,原primary 数据库默认不再是data guard 配置的一部分。

  • 多数情况下,其它逻辑/物理standby 数据库不直接参与failover 的过程,因此这些数据库不需要做任何操作。

  • 某些情况下,新的primary 数据库配置之后,需要重新创建其它所有的standby 数据库。

  • 如果打开了数据库闪回功能,failover后,主库通过闪回功能,还可以以standby的身份加到集群中。

3.1 将主库关闭,假设主库崩溃啦。

SQL> conn / as sysdba
Connected.
SQL> shutdown immediate
Database closed.
Database dismounted.
ORACLE instance shut down.

3.2 检查从库是否存在日志gap

查询待转换standby 数据库的V$ARCHIVE_GAP 视图,确认归档文件是否连接:

SQL> SELECT THREAD#, LOW_SEQUENCE#, HIGH_SEQUENCE# FROM V$ARCHIVE_GAP;


如果返回的有记录,按照列出的记录号复制对应的归档文件到待转换的standby 服务器。这一步非常重

要,必须确保所有已生成的归档文件均已存在于standby 服务器,不然可能会数据不一致造成转换时报错。

文件复制之后,通过下列命令将其加入数据字典:

SQL> ALTER DATABASE REGISTER PHYSICAL LOGFILE 'filespec1';

3.3 将从库切换成主库

SQL> select switchover_status from v$database;

SWITCHOVER_STATUS
------------------------------------------------------------
NOT ALLOWED

switchover是不允许的,我们要怎么办呢?

首先,取消日志应用

SQL> alter database recover managed standby database cancel;

Database altered.

再次,发出一个命令,模拟主库已经进行了数据库切换。在日志中打上EOR

SQL> alter database recover managed standby database finish;

Database altered.

 如果日志有gap,上面的命令将会失败,则需要执行ALTER DATABASE ACTIVATE PHYSICAL STANDBY DATABASE;

一旦finish操作完成,无论数据库原先的保护模式是什么,全部都会将为最大性能。为了保证新的主库一定能打开。

切换成主库,并打开数据库。

SQL> ALTER DATABASE COMMIT TO SWITCHOVER TO PRIMARY WITH SESSION SHUTDOWN;

Database altered.

SQL> ALTER DATABASE OPEN;

Database altered.

3.3 测试插入数据

SQL> conn scott/tiger
Connected.
SQL> select count(*) from t1;

  COUNT(*)
----------
	28

SQL> insert into t1 select * from t1;

28 rows created.

SQL> commit;

Commit complete.


四、使用Broker进行故障转移

故障转移后,如果原主库经过处理后,还能启动。而又想把原主库变成该DataGuard中的一个从库。则数据库必须打开数据库闪回功能。

4.1 开启数据库闪回。

SQL> alter database flashback on;

Database altered.

4.2 将主库关闭

SQL> select database_role from v$database;

DATABASE_ROLE
------------------------------------------------
PRIMARY

SQL> shutdown abort
ORACLE instance shut down.
SQL>

4.3 使用dgmgrl连到11gdg2上,进行Failover。

DGMGRL> connect sys/oracle@11gdg2   
Connected.
DGMGRL> FAILOVER TO 11GDG2;
Performing failover NOW, please wait...
Failover succeeded, new primary is "11gdg2"
DGMGRL> SHOW DATABASE VERBOSE 11GDG2;

Database - 11gdg2

  Role:            PRIMARY
  Intended State:  TRANSPORT-ON
  Instance(s):
    dgtst

  Properties:
    DGConnectIdentifier             = '11gdg2'
    ObserverConnectIdentifier       = ''
    LogXptMode                      = 'ASYNC'
    DelayMins                       = '0'
    Binding                         = 'OPTIONAL'
    MaxFailure                      = '0'
    MaxConnections                  = '1'
    ReopenSecs                      = '300'
    NetTimeout                      = '30'
    RedoCompression                 = 'DISABLE'
    LogShipping                     = 'ON'
    PreferredApplyInstance          = ''
    ApplyInstanceTimeout            = '0'
    ApplyParallel                   = 'AUTO'
    StandbyFileManagement           = 'AUTO'
    ArchiveLagTarget                = '0'
    LogArchiveMaxProcesses          = '4'
    LogArchiveMinSucceedDest        = '1'
    DbFileNameConvert               = ''
    LogFileNameConvert              = ''
    FastStartFailoverTarget         = ''
    InconsistentProperties          = '(monitor)'
    InconsistentLogXptProps         = '(monitor)'
    SendQEntries                    = '(monitor)'
    LogXptStatus                    = '(monitor)'
    RecvQEntries                    = '(monitor)'
    SidName                         = 'dgtst'
    StaticConnectIdentifier         = '(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=11gdg2.localdomain.com)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=11gdg2_DGMGRL)(INSTANCE_NAME=dgtst)(SERVER=DEDICATED)))'
    StandbyArchiveLocation          = 'USE_DB_RECOVERY_FILE_DEST'
    AlternateLocation               = ''
    LogArchiveTrace                 = '0'
    LogArchiveFormat                = '%t_%s_%r.dbf'
    TopWaitEvents                   = '(monitor)'

Database Status:
SUCCESS

DGMGRL>


4.4 恢复原主数据库

DGMGRL> show configuration

Configuration - DR

  Protection Mode: MaxPerformance
  Databases:
    11gdg2 - Primary database
    11gdg1 - Physical standby database (disabled)
      ORA-16661: the standby database needs to be reinstated

Fast-Start Failover: DISABLED

Configuration Status:
SUCCESS

先将11gdg1启动到mount

SQL> startup mount
ORACLE instance started.

Total System Global Area  839282688 bytes
Fixed Size		    2233000 bytes
Variable Size		  494931288 bytes
Database Buffers	  339738624 bytes
Redo Buffers		    2379776 bytes
Database mounted.
SQL>
DGMGRL> reinstate database 11gdg1;
Reinstating database "11gdg1", please wait...
Operation requires shutdown of instance "dgtst" on database "11gdg1"
Shutting down instance "dgtst"...
ORA-01109: database not open

Database dismounted.
ORACLE instance shut down.
Operation requires startup of instance "dgtst" on database "11gdg1"
Starting instance "dgtst"...
ORACLE instance started.
Database mounted.
Continuing to reinstate database "11gdg1" ...
Reinstatement of database "11gdg1" succeeded

成功啦!!

这个过程经历了很多次来回的测试,一直都是失败。主要的原因就是监听配置有问题。

静态监听,一定要配置db_unique_name。 而tnsname.ora中的连接字符串要指定到db_unique_name。

否则恢复原主库时,dgmgrl需要重启数据库,启动时则连接不上数据库。

下面列出监听和tns内容

11gdg1-> cat listener.ora 
# listener.ora Network Configuration File: /u01/app/oracle/product/11.2.0/db_1/network/admin/listener.ora
# Generated by Oracle configuration tools.

SID_LIST_LISTENER =
  (SID_LIST =
    (SID_DESC =
      (GLOBAL_DBNAME = 11gdg1_DGMGRL)
      (ORACLE_HOME = /u01/app/oracle/product/11.2.0/db_1)
      (SID_NAME = dgtst)
    )
    (SID_DESC =
      (GLOBAL_DBNAME = 11gdg1)
      (ORACLE_HOME = /u01/app/oracle/product/11.2.0/db_1)
      (SID_NAME = dgtst)
    )
  )

LISTENER =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = 11gdg1.localdomain.com)(PORT = 1521))
  )

ADR_BASE_LISTENER = /u01/app/oracle
11gdg1-> cat tnsnames.ora 
# tnsnames.ora Network Configuration File: /u01/app/oracle/product/11.2.0/db_1/network/admin/tnsnames.ora
# Generated by Oracle configuration tools.

11GDG1 =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.199.216)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVICE_NAME = 11gdg1)
    )
  )

11GDG2 =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.199.217)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVICE_NAME = 11gdg2)
    )
  )