靈活實現RAC三節點的負載均衡及TAF配置(四)

yangtingkun發表於2009-07-20

這兩天配置了一個三節點的RAC環境,想起前一段時間Thomas Zhang給我出的一個題目,配置一個三節點RAC環境的複雜負載均衡以及Transparent Application Failover的服務名。現在有環境了,可以將給出驗證後的結果了。

這篇解決例項1和例項2連續失敗導致的ORA-3113錯誤。

靈活實現RAC三節點的負載均衡及TAF配置(一):http://yangtingkun.itpub.net/post/468/482683

靈活實現RAC三節點的負載均衡及TAF配置(二):http://yangtingkun.itpub.net/post/468/482724

靈活實現RAC三節點的負載均衡及TAF配置(三):http://yangtingkun.itpub.net/post/468/487416

 

 

前面配置的TNSNAMES.ORA滿足了絕大部分的要求,但是有時如果例項1和例項2先後關閉,則客戶端在切換到另一個例項後,再次嘗試TAF的時候可能無法正確的連線到例項3上,而是報錯ORA-3113錯誤:

SQL> CONN TEST/TEST@SERVICEA
已連線。
SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac1

SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac2

SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;
SELECT INSTANCE_NAME FROM V$INSTANCE
*
ERROR
位於第 1 :
ORA-03113:
通訊通道的檔案結束

在上面3SQL執行之間,依次在後臺執行了下面的關閉例項的命令:

bash-2.03$ srvctl stop inst -d testrac -i testrac1
bash-2.03$ srvctl stop inst -d testrac -i testrac2

除了上面的ORA-3113錯誤,有時還可能出現ORA-1089錯誤:

SQL> CONN TEST/TEST@SERVICEA
已連線。
SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac1

SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac1

SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac1

SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac1

SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac2

SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac2

SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac2

SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac2

SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;
SELECT INSTANCE_NAME FROM V$INSTANCE
*
ERROR
位於第 1 :
ORA-01089:
正在進行緊急關閉 - 不允許進行任何操作


SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;
SELECT INSTANCE_NAME FROM V$INSTANCE
*
ERROR
位於第 1 :
ORA-03114:
未連線到 ORALCE

後臺執行的關閉例項的操作和前面的例子完全一樣,而得到的結果和剛才不一樣。這是由於這次在SQLPLUS中不斷的執行查詢,雖然已經執行了例項關閉的命令,但是Oracle後臺還沒有來得及關閉當前會話,導致會話仍然可以繼續執行,因此返回了多次testrac1和多次testrac2的結果。顯然ORA-1089錯誤也是由於這個原因,如果按照時間順序排列,會話執行先後可能碰到ORA-1089ORA-3113ORA-3114錯誤。

懷疑在執行TAF的時候,Oracle並沒有在FAILOVER發生的時候根據BACKUP指定服務名去動態的找到連線的資訊,這個連線資訊很可能是早就確定好的,等到FAILOVER的時候只是一個連線動作,發現連線不了,就直接報錯了。

於是將TNSNAMES.ORA中的SERVICEA_BACKUP服務名進行了調整,將前兩個FAILOVERBACKUP配置設定為預連線方式,避免在FAILOVER方式的時候找到一個不正確的例項進行連線:

SERVICEA_BACKUP =
  (DESCRIPTION_LIST =
    (LOAD_BALANCE = no)
    (DESCRIPTION =
      (ADDRESS_LIST =
        (ADDRESS = (PROTOCOL = TCP)(HOST = 172.25.198.224)(PORT = 1521))
      )
      (CONNECT_DATA =
        (SERVER = DEDICATED)
        (SERVICE_NAME = TESTRAC)
        (INSTANCE_NAME = TESTRAC1)
        (FAILOVER_MODE =
          (TYPE = SELECT)
          (METHOD = PRECONNECT)
          (BACKUP = SERVICEA_BACKUP)
        )
      )
    )
    (DESCRIPTION =
      (ADDRESS_LIST =
        (ADDRESS = (PROTOCOL = TCP)(HOST = 172.25.198.225)(PORT = 1521))
      )
      (CONNECT_DATA =
        (SERVER = DEDICATED)
        (SERVICE_NAME = TESTRAC)
        (INSTANCE_NAME = TESTRAC2)
        (FAILOVER_MODE =
          (TYPE = SELECT)
          (METHOD = PRECONNECT)
          (BACKUP = SERVICEA_BACKUP)
        )
      )
    )
    (DESCRIPTION =
      (ADDRESS_LIST =
        (ADDRESS = (PROTOCOL = TCP)(HOST = 172.25.198.227)(PORT = 1521))
      )
      (CONNECT_DATA =
        (SERVER = DEDICATED)
        (SERVICE_NAME = TESTRAC)
        (INSTANCE_NAME = TESTRAC3)
        (FAILOVER_MODE =
          (TYPE = SELECT)
          (METHOD = BASIC)
          (BACKUP = SERVICEA)
        )
      )
    )
  )

下面再次進行剛才的測試:

SQL> CONN TEST/TEST@SERVICEA
已連線。
SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac1

SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac2

SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac3

後臺對應的仍然是關閉例項1和例項2的操作:

bash-2.03$ srvctl start inst -d testrac -i testrac2,testrac1
bash-2.03$ srvctl stop inst -d testrac -i testrac1
bash-2.03$ srvctl stop inst -d testrac -i testrac2

當然這個方法不能治本,繼續前面的測試:

SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac3

SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac1

SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;

INSTANCE_NAME
----------------
testrac2

SQL> SELECT INSTANCE_NAME FROM V$INSTANCE;
SELECT INSTANCE_NAME FROM V$INSTANCE
*
ERROR
位於第 1 :
ORA-03113:
通訊通道的檔案結束

後臺對應的操作:

bash-2.03$ srvctl start inst -d testrac -i testrac2,testrac1
bash-2.03$ srvctl stop inst -d testrac -i testrac3
bash-2.03$ srvctl stop inst -d testrac -i testrac1
bash-2.03$ srvctl start inst -d testrac -i testrac3
bash-2.03$ srvctl stop inst -d testrac -i testrac2

描述一下上面的測試過程。當前會話連線到例項3上,下面啟動例項1和例項2,並關閉例項3。發現會話切換到例項1上。然後關閉例項1,這時會話切換到例項2上。將例項3啟動,然後關閉例項2,如果TAF工作正常,應該可以切換到例項3上,但是這裡出現了ORA-3113錯誤。

顯然Oracle只是在第一次連線的時候嘗試登陸BACKUP指定的預連線例項,如果連線不上,Oracle在當前會話需要執行TAF的時候報錯。

 

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4227/viewspace-609766/,如需轉載,請註明出處,否則將追究法律責任。

相關文章