经过前面的实验我们已经搞定了服务器端的SWITCH OVER 和FAST FAILE OVER
那现在我们来搞定客户端或者是应用服务器端的自动切换到合适的数据库服务器上.
当主数据库无法连接后,等待规定的时间,去连接新的主数据库. 这个时间段是BROKER监控时间,并完成备库变成主库的操作.
目前我们已经完成了一次FAST FAILE OVER. 所以DBMAST是备库啦, DBSALVE是主库呢!
看新备库的监听状态
另外上篇 FAILE OVER 遇到没注册的问题应该是DG 没启动自动注册功能
SQL> alter system setlocal_listener=dbsalve scope=both;
系统已更改。
SQL> show parameter local
NAME TYPE VALUE
--------------------------------------------------------------------- ------------------------------
_local_communication_costing_enabledboolean TRUE
local_listener string DBSALVE
log_archive_local_first boolean TRUE
parallel_force_local boolean FALSE
SQL> alter system register;
系统已更改。
SQL>
监听的情况
[oracle@DB-Salve admin]lsnrctl status
LSNRCTL for Linux: Version 11.2.0.4.0 -Production on 27-4月 -2016 11:31:41
Copyright (c) 1991, 2013, Oracle. All rights reserved.
正在连接到(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.0.202)(PORT=1521)))
LISTENER 的 STATUS
------------------------
别名 LISTENER
版本 TNSLSNRfor Linux: Version 11.2.0.4.0 - Production
启动日期 27-4月 -201611:17:26
正常运行时间 0 天 0 小时 14 分 14 秒
跟踪级别 off
安全性 ON: LocalOS Authentication
SNMP OFF
监听程序参数文件 /u01/app/software/oracle/product/11.2.0/db_1/network/admin/listener.ora
监听程序日志文件 /u01/app/software/oracle/diag/tnslsnr/DB-Salve/listener/alert/log.xml
监听端点概要...
(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=192.168.0.202)(PORT=1521)))
服务摘要..
服务 "DBMASTXDB" 包含 1 个实例。
实例"DBSALVE", 状态 READY, 包含此服务的 1 个处理程序...
服务 "DBSALVE" 包含 2 个实例。
实例"DBSALVE", 状态 UNKNOWN, 包含此服务的 1 个处理程序...
实例"DBSALVE", 状态 READY, 包含此服务的 1 个处理程序...
服务 "DBSALVE_DGB" 包含 2 个实例。
实例"DBSALVE", 状态 UNKNOWN, 包含此服务的 1 个处理程序...
实例"DBSALVE", 状态 READY, 包含此服务的 1 个处理程序...
服务 "DBSALVE_DGMGRL.shark.com" 包含 1 个实例。
实例"DBSALVE", 状态 UNKNOWN, 包含此服务的 1 个处理程序...
服务 "DG_TAF" 包含 1 个实例。
实例"DBSALVE", 状态 READY, 包含此服务的 1 个处理程序...
命令执行成功
连接到:
Oracle Database 11g Enterprise EditionRelease 11.2.0.4.0 - 64bit Production
With the Partitioning, OLAP, Data Miningand Real Application Testing options
SQL> select db_unique_name fromv$database;
DB_UNIQUE_NAME
------------------------------
DBSALVE
SQL> select db_unique_name fromv$database;
select db_unique_name from v$database
*
第 1 行出现错误:
ORA-25408: 无法安全重放调用
SQL> select db_unique_name fromv$database;
DB_UNIQUE_NAME
------------------------------
DBMAST
SQL>
TAF(Transparent Application Failover)
这块的配置,参考:
10g & 11g Configuration of TAF(TransparentApplication Failover) and Load Balancing [ID 453293.1]
现在的大部分流行的应用系统(如:weblogic, Jboss),都是启动时就建立若干到数据库的长连接,在应用程序整个生命周期内重用这些连接。 而Client-Side Connet Time Failover的工作方式使它对应用程序的可用性没有太大帮助。
所以从Oracle 8.1.5 版本只有引入了新的Failover 机制—TAF。 所谓TAF,就是连接建立以后,应用系统运行过程中,如果某个实例发生故障,连接到这个实例上的用户会被自动迁移到其他的健康实例上。对于应用程序而言,这个迁移过程是透明的,不需要用户的介入,当然,这种透明要是有引导的,因为用户的未提交事务会回滚。 相对与Client-Side Connect Time Failover的用户程序中断,抛出连接错误,用户必须重启应用程序,TAF 这种方式在提高HA上有了很大的进步。
TAF 的配置也很简单,只需要在客户端的tnsnames.ora中添加FAILOVER_MODE配置项。这个条目有4个子项目需要定义。
1.METHOD: 用户定义何时创建到其实例的连接,有BASIC 和 PRECONNECT 两种可选值。
BASIC: 是指在感知到节点故障时才创建到其他实例的连接。
PRECONNECT: 是在最初建立连接时就同时建立到所有实例的连接,当发生故障时,立刻就可以切换到其他链路上。
两种方法比较: BASIC方式在Failover时会有时间延迟,PRECONNECT方式虽然没有时间延迟,但是建立多个冗余连接会消耗更多资源,两者就是是用时间换资源和用资源换时间的区别。
2. TYPE: 用于定义发生故障时对完成的SQL 语句如何处理,其中有2种类型:session 和select.
这2种方式对于未提交的事务都会自动回滚,区别在于对select 语句的处理,对于select,用户正在执行的select语句会被转移到新的实例上,在新的节点上继续返回后续结果集,而已经返回的记录集则抛弃。
假设用户正在节点1上执行查询,整个结果集共有100条记录,现在已从节点1上返回10条记录,这时节点1宕机,用户连接被转移到节点2上,如果是session模式,则需要重新执行查询语句;如果是select方式,会从节点2上继续返回剩下的90天记录,而已经从节点1返回的10条记录不会重复返回给用户,对于用户而言,感受不到这种切换。
显然为了实现select 方式,Oracle 必须为每个session保存更多的内容,包括游标,用户上下文等,需要更多的资源也是用资源换时间的方案。
3. DELAY 和 RETRIES: 这2个参数分别代表重试间隔时间和重试次数。
示例:
RAC =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = rac1-vip)(PORT =1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = rac2-vip)(PORT =1521))
(LOAD_BALANCE=YES)
(
CONNECT_DATA=
(SERVER=DEDICATED)
(SERVICE_NAME=RAC)
(
FAILOVER_MODE=
(TYPE=session)
(METHOD=basic)
(RETRIES=180)
(DELAY=5)
)
)
)
DBMAST =
(DESCRIPTION =
(LOAD_BALANCE=OFF)
(FAILOVER=on)
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.200)(PORT = 1521))
(CONNECT_DATA =
(SERVICE_NAME = DBMAST)
(FAILOVER_MODE=
(backup=DBSALVE)
(TYPE=select)
(METHOD=basic)
(RETRIES=5)
(DELAY=30)
)
)
)
DBSALVE =
(DESCRIPTION =
(LOAD_BALANCE=OFF)
(FAILOVER=on)
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.202)(PORT = 1521))
(CONNECT_DATA =
(SERVICE_NAME = DBSALVE)
(FAILOVER_MODE=
(backup=DBMAST)
(TYPE=session)
(METHOD=basic)
(RETRIES=5)
(DELAY=30)
)
)
)
DG_TAF =
(DESCRIPTION =
(LOAD_BALANCE= OFF )
(FAILOVER= ON )
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.202)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.200)(PORT = 1521))
)
(CONNECT_DATA =
(SERVICE_NAME = DG_TAF)
(FAILOVER_MODE=
(TYPE= SELECT)
(METHOD= BASIC)
(RETRIES=5)
(DELAY=30)
)
)
)
测试结果令人不满意因为如果只是主数据库的实列挂了,不能提供服务,可主数据库的监听还在,还在继续提供连接服务.
可测试的FAILE OVER 可以短时间转移到备库上. 当这时候备库还在处于备库状态啊.
没经过重试5次,每次30秒去连接主库,如果最终重试失败后才去连接备库.
连名博大神级人物 DAVE 也没说明白
http://blog.csdn.net/tianlesoftware/article/details/6085523
虽然他做的测试强调要把主库的监听给停了, 然后这不是很现实,现实情况大部分是主数据库实列不可用. 整个数据库服务器挂的可能性很小. 我想DAVE 也是做了简单的介绍和简单的测试.
最后我想到了一点… 当主库和备库 哪个是主库角色的时候,动态注册个服务
先注册个服务
begin
dbms_service.create_service
(service_name=>'I_AM_MAIN_DB',
NETWORK_NAME=>'DG_FAIL_OVER',
AQ_HA_NOTIFICATIONS=>TRUE,
FAILOVER_METHOD=>'BASIC',
FAILOVER_TYPE=>'SELECT',
FAILOVER_RETRIES=>60,
FAILOVER_DELAY=>5
);
END;
/
通过存储过程来启动和个关闭服务
create or replace procedure dg_taf_proc is
v_roleVARCHAR(30);
-- IF V_ROLE ='PRIMARY'
begin
SELECT DATABASE_ROLE INTO V_ROLE FROM V$DATABASE;
IF V_ROLE='PRIMARY'
THEN
DBMS_SERVICE.START_SERVICE('I_AM_MAIN_DB');
ELSE
DBMS_SERVICE.STOP_SERVICE('I_AM_MAIN_DB');
END IF;
end ;
通过两个触发器来执行存储过程.
create or replace trigger dg_taf_starup
after startup on database
begin
dg_taf_proc;
end;
create or replace trigger dg_taf_role_change
after db_role_change on database
begin
dg_taf_proc;
end;
客户端配置
DG_TAF =
(DESCRIPTION =
(LOAD_BALANCE= OFF )
(FAILOVER= ON )
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.202)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.200)(PORT = 1521))
)
(CONNECT_DATA =
(SERVICE_NAME = DG_FAIL_OVER)
(FAILOVER_MODE=
(TYPE= SELECT)
(METHOD= BASIC)
(RETRIES=5)
(DELAY=30)
)
)
)
测试吧
SQL> shutdown abort;
ORACLE 例程已经关闭。
DGMGRL> start OBSERVER;
观察程序已启动
16:04:19.18 2016年4月27日星期三
正在为数据库 "DBMAST" 启动快速启动故障转移...
立即执行故障转移, 请稍候...
故障转移成功, 新的主数据库为 "DBMAST"
16:04:29.55 2016年4月27日星期三
新主库的监听看见了动态注册的服务了
(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=localhost)(PORT=1521)))
服务摘要..
服务 "DBMAST" 包含 1 个实例。
实例"DBMAST", 状态 READY, 包含此服务的 1 个处理程序...
服务 "DBMASTXDB" 包含 1 个实例。
实例"DBMAST", 状态 READY, 包含此服务的 1 个处理程序...
服务 "DBMAST_DGB" 包含 1 个实例。
实例"DBMAST", 状态 READY, 包含此服务的 1 个处理程序...
服务 "DBMAST_DGMGRL.shark.com" 包含 1 个实例。
实例"DBMAST", 状态 UNKNOWN, 包含此服务的 1 个处理程序...
服务 "DBSALVE" 包含 1 个实例。
实例"DBMAST", 状态 UNKNOWN, 包含此服务的 1 个处理程序...
服务"DG_FAIL_OVER" 包含 1 个实例。
实例 "DBMAST", 状态 READY, 包含此服务的 1 个处理程序...
命令执行成功
而客户端已经连接上的回话,确实发生了重试等待.最后就连上了新主库.