数据库容灾的设计与实现(四)

五、实现客户端的自动故障转移

当数据库产生故障不得不进行切换时,大多会发生客户端连接中断或丢失的情况。而在这种情况下有时不得不重新连接数据库,甚至修改服务器IP地址或重新启动中间件服务器,让应用服务器重新正确连接到数据库上。因此,期间发生的连接中断是不可避免的,无法满足企业对应用高可靠性的要求,更让数据级容灾系统的效果大打折扣。

客户端和Oracle数据库的连接主要有OCI及JDBC两种方式,TAF仅支持OCI的连接方式,在油田实际应用开发中90%以上的应用服务器采用了OCI的连接方式,对于JDBC,可以使用JDBC OCI驱动,来支持TAF。下面研究OCI客户端的故障转移。

本文在此提出服务器端使用触发器的方法,并且设置OCI客户端基于透明故障迁移的TAF (Transparent Application Failover)连接方法,使得用户在连接时或发生数据库正常切换及故障Broker Failover时,客户端始终保持对数据库的正确连接。其效果对客户端来说是透明且连续的,让用户感觉不到数据库后台已经发生了巨大的变化,从而证明基于Oracle Data Guard的数据级容灾系统是完全适用于生产的,是完全成熟可靠的容灾系统。

(一)OCI客户端如何连接到Oracle数据库

要清晰明了的了解客户端透明故障迁移技术,就必须先了解客户端是如何连接到 Oracle数据库的。

客户端连接到数据库,除了需要在客户端机器上安装Oracle的客户端软件外,客户端一般需要配置 sqlnet.ora 和 tnsnames.ora 两个文件,数据库端需要配置listener.ora,数据库之间的连接,也需要我们在数据库服务器配置tnsnames.ora。数据库服务器上这些文件默认的目录为$ORACLE_HOME/network/admin。

数据库启动之后,要想提供网络服务,客户端通过远程连接访问,需要启动数据库的监听器(配置文件通常为listener.ora)监听器用于在特定的端口上(缺省的端口是1521)提供监听,接收来自客户端的访问请求(客户端请求通过tnsnames.ora文件定义发送)。在专用服务器模式下(Dedicated)监听器会为每个请求衍生一个服务器进程相对应,通过这个服务器进程将客户端与数据库联系起来。下图描述了建立网络连接时客户端以及服务器端的相关文件及关系。

接下来介绍一下客户端以及服务器端为提供网络应用必须执行的相关配置,这些配置可以通过 Oracle 的工具 Net Configuration Assistant 来进行。

1. 客户端的TNSNAMES.ORA文件配置

客户端为了连接Oracle数据库服务器,需要安装客户端软件,并在客户端配置网络服务名文件(当然Oracle支持多种连接方式,这里主要介绍网络服务名文件方式连接,也就是 tnsnames.ora 文件),这个配置文件位于$ORACLE_HOME/network/admin 目录下,在 Windows 和UNIX/Linux上的位置是相同的,文件名为tnsnames.ora。

一段典型的配置如下:

orajy=

  (description=

      (address_list=

      (address=(protocol=tcp)(host=10.79.20.51)(port=1521))

    )

    (connect_data=

      (service_name=orajy)

      (server=dedicated)

    )

  )

这里的ADDRESS部分包含了服务器的地址及监听端口信息,CONNECT_DATA部分包 含了连接信息,用于定义目标服务的名称 SERVICE_NAME在这里用于识别访问的数据库服务;SERVICE_NAME在这里也经常可以用SID来替代,从Oracle 9i开始,Oracle推荐使 用 SERVICE_NAME 而不是 SID。 

配置完成之后,可以通过tnsping工具进行连通性测试:

如果能够顺利通信,则可以通过SQL*Plus或其他工具通过网络服务名进行数据库网络访问:

SQL> connect system/orac1e@orajy

 Connected.

特殊地,除了 tnsnames.ora文件之外,Oracle支持通过SQL*Plus直接连接远程或本地数据库,当然需要在连接时指定必须的参数信息,例如:

SQL>conn kfsyb/kfsybpw@(description= (address=(protocol=tcp)(host=10.79.20.51)(port=1521))(connect_data=      (service_name=orajy)))

Connected.

连接本地数据库可以使用类似如下方式:

SQL>conn fsyb/kfsybpw@(description= (address=(protocol=tcp)(host=localhost)(port=1521))(connect_data=      (service_name=orajy)))

Oracle 10g开始,还可以使用如下方式进行连接:

SQL> connect kfsyb/kfsybpw @loca1host:1521/orajy

前面说的是客户端,在服务器端数据库中存在一个初始化参数 SERVICE_NAME,这个参数就是用于定义客户端请求的数据库服务名。

Oracle文档中这样定义这个初始化参数:SERVICE_NAMES为实例所连接的数据库定义一个或多个服务名,可以通过定义多个服务名将不同用户连接区分开来。这个参数的缺省格式为DB_NAME.DB_DOMAIN,如果定义了 DB_DOMAIN那么定义的服务名 就类似:

SERVICE_NAMES - sales.fksyb.com. news.kfsyb.com

通过这样的定义,销售用户可以通过在客户端定义SALES服务名来建立连接,而新闻用户则可以通过NEWS服务名进行连接,最终用户可以不必关注数据库是哪一个,他们只需要关心服务名。

RAC环境中,tnsnames.ora参数配置会有所不同。

2. 服务器端的监听器文件listener.ora配置

说完了客户端再来看一下,如果数据库端设置了 SERVICE_NAMES后,监听器应该怎样配置。例如以下一个数据库系统,为数据库设置多个服务名(通过SCOPE = both设置,同时修改了参数文件):

SQL> show parameter service_name

SQL> alter system set servlce_names= 'sales,news' scope=both;

同样在$ORACLEHOME/network/admin目录下可以找到listener.ora文件,以下是一个监听器文件的典型配置:

LISTENER=

(DESCRIPTION_LIST =

(DESCRIPTION =

 (ADORESS_LIST = (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC))

)

(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=10.79.20.51)

(PORT=1521))

)

SID_LIST_LISTENER =

 (SID_LIST=

(SID_DESC= (SID_NAME = PLSExtProc)

(ORACLE_HOME =/app/oracle/product/9.2.0)

(PROGRAM = extproc)

)

(SID_DESC =

(GLOBAL_DBNAME=sales)

(ORACLE_HOME =/app/oracle/product/9.2.0)

   (SID_NAME=orajy)

)

(SID_DESC = (GLOBAL_DBNAME =news)

(ORACLE_HOME =/app/oracle/product/9.2.0)

   (SID_NAME =orajy)

)

)

监听器文件主要包括两个部分。

第一部分LISTENER信息,这部分包含了监听的协议、地址以及端口等信息.

第二部分SID_LIST_LISTENER信息,这部分信息用于提供对外的数据库服务列表。第一个SID_DESC部分(SID_NAME = PLSExtProc )是数据库缺省就包含的对外部存储过程提供的本地监听,此外两个SID_DESC部分就是对数据库的两个SERVICE_NAMES所设置的监听服务,对于同一个SID对应的数据库可以对外提供多个服务名供客户端访问.

设置服务名的参数为GLOBAL_DBNAME,当处理客户端连接请求时,监听器首先尝试将GLOBAL_DBNAME和客户端请求中的SERVICE_NAME相匹配;如果客户端连 接请求的是SID信息,则Oracle不检査GLOBAL_DBNAME设置,而是对监听器中设置的SID_NAME进行匹配。

启动这个监听器后,可以看到对于不同服务名Oracle所启动的监听信息。

通过服务名,Oracle可以将客户端和服务器彻底隔离开来,对于客户端来说,它不用关心数据库的名字、实例名到底是什么,它只需要知道数据库对外提供的服务名就行了,这个名字可能和实例名相同,也可能不相同。

3. 动态监听器注册服务

从 Oracle 8i 开始,Oracle 引入了动态服务注册(Dynamic Service Registration)的功能,所谓动态注册是指当实例启动之后,由后台进程PMON在监听器中注册数据库服务信息。在动态注册机制下,原来监听器中的SID_LIST部分将不再需要。

通过服务注册可以获得如下收益。

(1)简化配置

服务注册可以减化监听器的配置,SID_LIST_<listener_name>参数将不再需要。

(2)连接时Failover

在动态注册时,由数据库主动向监听器注册实例,因此监听器总是可以知道实例的状态, 在RAC环境下,当某个数据库实例出现故障时,动态服务注册功能可以快速自动地Failover客户端请求到其他实例;而如果在静态注册模式下,监听器将首先启动一个专用服务器进程 接受客户端请求,然后向数据库服务器发起连接,随后才能发现实例已经停止,给出“Oracle not available"的错误提示,这个过程要缓慢低效得多。

(3)运行时连接负载均衡

服务注册使得监听器能够向负载最轻的实例转发连接请求,从而实现运行时连接的负载均衡。

动态注册在Oracle 9i里是自动启用的,监听器文件可以不再需要,或者可以配置一个经过极大简化的监听器文件。现在一个简单的监听器配置可能类似如下示例(缺省的监听 PLSExtProc是为外部存储过程调用而配置的)

LISTENER=

(DESCRIPTION_LIST=

 (DESCRIPTION =

(ADDRESS_LIST =

(ADDRESS = (PROTOCOL = TCP)(HOST= 10.79.20.51)(PORT= 1521))

)

(ADDRESS_LIST =

(ADDRESS = (PROTOCOL = IPC)(KEY= EXTPROC))

)

)

)

SID_LIST_LISTENER=

 (SID_LIST= 

(SID_DESC=

  (SID_NAME = PLSExtProc)

(ORACLE_HOME=/opt/oracle9/product/9.2.0)

  (PROGRAM = extproc)

)

 )

己经启动的实例随后会将服务名(初始化参数中定义的SERVICE_NAMES)注册到监听器中动态注册的服务名,由于监听器确切地知道实例的状态,所以正常状态通常显示为READY,而对于静态注册的服务名,则状态显示为UNKNOWN,这也是我们经常看到某些数据库的监听器会有如下显示的原因:

Services Summary...

Service "PLSExtProc" has 1 instance(s).

Instance "PLSExtProc". status UNKNOWN. has 1 handler(s) for this service...

Service "hsblll" has 2 instance(s).

Instance "hsblll", status UNKNOWN, has 1 handler(s) for this service...

Instance "hsblll". status READY, has 1 handler(s) for this service...

如果监听器具有缺省的名称、端口及协议,则无需任何特殊配置,Oracle就能执行动态注册。但是如果监听器具有非缺省配置,则需要设置LOCAL_LISTENER参数。

对于专用服务器模式,参数可以设置为:

LOCAL_USTENER=listener_alias

对于共享服务器模式,参数可以设置为:

DISPA TCHERS= "(PROTOCOL==tcp)(USTENER=iistener_alias) ”

Listener_alias随后通过Oracle命名方式(例如tnsnames.ora文件)解析为其他协议地址。 

例如,如果监听器监听端口为1522,可以设置初始化参数为:

LOCAL_LISTENER=listenerl

对于共享服务器模式,可以设置为:

DISPATCHERS="(PROTOCOL=tcp)(LISTENER=listenerl)"

在tnsnames.ora文件中listener1可以按如下方式解析:

listenerl=

(DESCRIPTION=

(ADDRESS=(PROTOCOL=tcp)(HOST=prod-server)(P0RT=1522)))

4. 配置和管理Oracle Network 的工具

可以使用以下任一工具或应用程序管理Oracle Network 配置:

(1)Enterprise Manager:提供了配置和管理Oracle Net Services 的集成环境。使用Enterprise Manager 可在跨多个文件系统的任何Oracle 主目录中配置Oracle Net Services,还可配置Oracle Net Services 来管理监听程序。

(2)Oracle Net Manager:提供一个图形用户界面(GUI),通过这个界面可在本地客户机或服务器主机的Oracle 主目录中配置Oracle Net Services。

(3)Oracle Net Configuration Assistant:安装Oracle 软件时通过Oracle Universal Installer 来启动。使用Oracle Net Configuration Assistant 可配置Oracle 数据库的监听协议地址和服务信息。

(4)命令行:用于启动、停止监听程序进程或查看监听程序进程的状态。由操作系统用户(在本程中为Oracle)启动或停止监听程序。

(二)服务器端实现
1. Oracle触发器概念

触发器是特定事件出现的时候,自动执行的代码块。类似于存储过程,触发器与存储过程的区別在于存储过程是由用户或应用程序显式调用的,而触发器是不能被直接调用的。

特别需要提出的是,只需要在主库执行相关创建服务及触发器的命令就可以了, 因为在Data Guard的架构下,新创建的对象会自动同步到备库上,无需二次执行。

2. 编写触发器提供统一服务名

编写一个触发器,在数据库切换主备库的时候,根据V$DATABASE里的DATABASE_ROLE的值是否是'PRIMARY'来启动一个统一的服务名提供客户端连接。相关代码如下:

以下内容分别主库服务器上完成,这里假设数据库的监听端口为默认的1521。

(1)首先创建一个服务名为orajy_prod。

SQL>exec DBMS_SERVICE.CREATE_SERVICE('orajy_prod','orajy_prod');

服务名创建完成后,通过动态的注册服务,向外提供服务名orajy_prod。如果这里假设数据库的监听端口为默认的1521,如果不是请参考上文中内容,设置LOCAL_LISTENER参数,实现动态注册服务。

(2)创建一个触发器:

create or replace trigger manage_service

after DB_ROLE_CHANGE on database

declare role varchar(30);

begin select database_role into role from v$database;

  if role = 'PRIMARY' then DBMS_SERVICE.START_SERVICE(' orajy_prod ');

else DBMS_SERVICE.STOP_SERVICE(' orajy_prod ');

end if;

end;

如果Data Guard配置中REDO没有使用实时应用( real-time apply),需要归档当前的redo log确保上面改变应用到备库上。 

SQL> ALTER SYSTEM ARCHIVE LOG CURRENT;

当数据库启动后,假如数据库的角色为主库(role='PRIMARY'),则启动服务orajy_prod提供客户端连接。执行该触发器后,数据库会在进行正常切换或执行Broker Failover后,始终在主库上运行服务orajy_prod,提供客户端不间断的对外连接服务。 至于是主库还是备库提供的服务,从客户端的角度来讲无需知晓,客户端也只需要认准服务名orajy_prod就可以,从而实现透明无故障切换。当然上述透明故障转移功能还需要TAF技术的支持。

(三)客户端使用TAF连接

TAF为Transparent Application Failover的缩写,一般应用TAF都是在OPS/RAC环境中,为RAC提供无延时的透明迁移。本文在这里重点研究单实例(非RAC)的Data Guard环境中客户端的故障切换配置,使得客户端不会因为数据库切换而中断连接,使用户在使用中感觉不到后台数据库的切换或失败转移带来的影响。

1. 实现原理

在Data Guard环境中,客户端的自动故障切换时通过Fast Application Notification (FAN)[20] 和Transparent Application Failover (TAF)完成的。过程如下:

(1)一个OCI客户端连接到主数据库的时候,更新数据库中的表REG$,包含客户端的IP地址,并把同样的信息复制到备库。

(2)当进行failover故障切换时, Data Guard broker 在备库的警告日志中插入一个 DB Down 事件信息,并把它通知给表REG$中所有的客户端。注意这种自动客户端故障转移的方法需要failover由Data Guard broker来进行管理。

(3)当客户端收到DB Down 事件,迅速中断与故障主库的联系。 

(4)TAF技术使OCI客户端自动尝试建立一个新的连接到服务名orajy_prod上。orajy_prod服务名见上文。

2. 客户端配置

客户端机器上安装Oracle的客户端软件外,sqlnet.ora和tnsnames.ora做如下配置。

(1)创建保护主数据库和备数据库主机的tnsnames.ora配置文件

orajy_prod =

  (DESCRIPTION =

   (ADDRESS_LIST =

    (FAILOVER = ON)

    (LOAD_BALANCE = OFF)

    (ADDRESS = (PROTOCOL = TCP)(HOST = 10.79.20.51)(PORT = 1521))

    (ADDRESS = (PROTOCOL = TCP)(HOST =10.79.20.54)(PORT = 1521))

    )

    (CONNECT_DATA =

     (SERVICE_NAME = orajy_prod)

(FAILOVER_MODE=

(TYPE=session) (METHOD=BASIC) (RETRIES=180) (DELAY =2)

)

     )

   )

(3)设置sqlnet.ora参数

SQLNET.OUTBOUND_CONNECT_TIMEOUT =3

  

由于启用了FAILOVER的模式,故当主库发生切换时,客户端会自动搜索其中列出的IP地址,并自动连接到切换后主库的orajy_prod服务。客户端始终保持对数据库的正确连接,其效果对客户端来说是透明且连续的,让用户感觉不到数据库后台已经切换到另外一台服务器上了。所以通过使用以上方法完全可以使Oracle Data Guard的数据级容灾系统完全适用于生产环境,给企业带来极大的效益。

本章小结

本章在Broker Failover的基础上提出了使用触发器的方法,并且设置基于透明故障转移的TAF连接方法,使得数据库在发生切换时保持对OCI客户端提供不间断的连接。 其效果对客户端来说是透明且连续的,让用户感觉不到数据库后台已经发生了巨大的变化,保障了业务的连续运行。

  • 35
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值