1

我面临一个愚蠢的问题,但经过一段时间的在线搜索和试验,我开始失去希望。
感谢 Dataguard,我有两个配置为副本的 Oracle 数据库。

我正在使用 JDBC TNS URL 连接到我的数据库,例如:

jdbc:甲骨文:瘦:@
  (DESCRIPTION_LIST=
    (故障转移=开启)
    (负载平衡=关闭)
    (描述=
      (地址=
        (协议=TCP)
        (HOST= DB1 )
        (端口=1521))
        (连接数据=
          (服务器=专用)
          (SID=我的SID))
        )
    (描述=
      (地址=
        (协议=TCP)
        (HOST= DB2 )次要
        (端口=1521))
        (连接数据=
          (服务器=专用)
          (SID=我的SID))
        )
    )

当我执行切换时,角色会交换:DB1 变为辅助,DB2 变为主。DB1 处于挂载状态。
到目前为止,一切都很好。

但是使用我的连接 URL,我希望从 DB2 获得连接,该连接已成为主要但由于 DB1 侦听器仍在运行,它表现得好像一切正​​常,我最终尝试在 DB1 上获得连接,这导致以下错误:

ORA-01033: ORACLE 初始化或关闭正在进行中

如果我终止了侦听器,那么故障转移将起作用,并且我从 DB2 获得了连接。

但 dataguard 的全部意义在于执行自动故障转移。
但是,如果我被迫杀死听众:

  1. 这不是我所期待的:)
  2. 切换可能不起作用,因为它使用侦听器来这样做

如果有人知道正确配置的线索,我很感兴趣!

提前致谢。

4

2 回答 2

1

经过长时间的尝试寻找合适的解决方案,我很确定这种机制强烈依赖于侦听器:故障转移机制只有在侦听器停止时才能正常工作
知道了这一点,我最终决定实现自己的解决方案,而不涉及应用程序代码。

由于我无法使用原始侦听器,因为 Dataguard 使用它们来执行其操作,所以我复制了所有侦听器。例如,对于端口 1521 上的 LISTENER_DB1,我在端口 1531 上创建了 LISTENER_DB1_FO(FO 代表您可能已经猜到的故障转移)。

从应用程序的角度来看,我的配置变为:

jdbc:甲骨文:瘦:@
  (DESCRIPTION_LIST=
    (故障转移=开启)
    (负载平衡=关闭)
    (描述=
      (地址=
        (协议=TCP)
        (HOST=DB1) 主
        (端口= 1531 ))
        (连接数据=
          (服务器=专用)
          (SID=我的SID))
        )
    (描述=
      (地址=
        (协议=TCP)
        (HOST=DB2) 辅助
        (端口= 1531 ))
        (连接数据=
          (服务器=专用)
          (SID=我的SID))
        )
    )

感谢一位帮助我的同事,我编写了一个脚本来检查数据库角色是否是主要的(即使数据库处于挂载状态也可以工作)。从那个答案,我的脚本将启动或停止相关的侦听器。

#! /bin/bash export ORACLE_HOME=<YOUR_HOME> export ORACLE_BIN=$ORACLE_HOME/bin/ DATABASE_ROLE() { export ORACLE_SID=$1 request='SELECT DATABASE_ROLE FROM V$DATABASE' result=`$ORACLE_BIN/sqlplus -silent / as sysdba << EOF set pages 0 feedback off
${request}; exit EOF` echo ${result} } for DBNAME in DB1 DB2 DB3 do $ORACLE_BIN/lsnrctl status LISTENER_${DBNAME}_FO > /dev/null return_status=$? if [ "$(DATABASE_ROLE ${DBNAME})" != 'PRIMARY' ];then echo "DB ${DBNAME} is secondary" if [ $return_status -eq 0 ];then $ORACLE_BIN/lsnrctl stop LISTENER_${DBNAME}_FO fi else echo "DB ${DBNAME} is primary" if [ $return_status -eq 1 ];then $ORACLE_BIN/lsnrctl start LISTENER_${DBNAME}_FO fi fi done

然后我 cronned 那个脚本。唯一的“缺点”是两次 cron 执行之间的最小间隔是一分钟。如果您不走运,您的故障转移检测可能需要 59 秒才能被检测到。

但我们已经对其进行了几天的测试,它就像一个魅力。

如果有人有正确的解决方案或更好的主意,请不要犹豫!谢谢。

于 2017-07-20T14:30:18.510 回答
0

可以在主服务器和备用服务器上创建具有相同名称的服务。可以使用服务名称修改连接。仅在当前主节点上保持服务。

于 2018-05-31T10:04:54.577 回答