Oracle

為什麼 tnsnames 不能正確故障轉移到備用數據庫?

  • February 23, 2022

我有這個 tnsnames:

JUPITER =
 (DESCRIPTION =
  (ADDRESS_LIST =
   (LOAD_BALANCE = OFF)
   (FAILOVER = ON)
   (ADDRESS = (PROTOCOL = TCP)(HOST = rac-scan.mercurio.sp)(PORT = 1521))
   (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.85)(PORT = 1521))
  )
   (CONNECT_DATA =
     (SERVER = DEDICATED)
     (SERVICE_NAME = jupiter)
   )
 )

)

rac-scan.mercurio.sp是 prod test db 的掃描並且192.168.0.85是備用數據庫。

當我停止 prod db 並嘗試連接時,它仍然引導我到 prod dbrac-scan.mercurio.sp

我的步驟:

使用 tns 別名測試與 prod 數據庫的連接:

C:\Users\Danilo>sqlplus sys/xxxxxx@jupiter as sysdba

SQL*Plus: Release 19.0.0.0.0 - Production on Wed Feb 9 10:55:09 2022
Version 19.6.0.0.0

Copyright (c) 1982, 2019, Oracle.  All rights reserved.


Connected to:
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production

SQL> select database_role from v$database;

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

一切正常,現在我將停止這個數據庫:

停止主數據庫

(rac1)(oracle@jupiter1):~> srvctl stop database -d jupiter -o immediate

現在我嘗試使用相同的 tns 別名再次連接

C:\Users\Danilo>sqlplus sys/xxxxxx@jupiter as sysdba

SQL*Plus: Release 19.0.0.0.0 - Production on Wed Feb 9 10:58:47 2022
Version 19.6.0.0.0

Copyright (c) 1982, 2019, Oracle.  All rights reserved.

Connected to an idle instance.

使用非 sysdba 帳戶

C:\Users\Danilo>sqlplus user_test/xxxxx@jupiter

SQL*Plus: Release 19.0.0.0.0 - Production on Wed Feb 9 11:12:27 2022
Version 19.6.0.0.0

Copyright (c) 1982, 2019, Oracle.  All rights reserved.

ERROR:
ORA-01034: ORACLE not available
ORA-27101: shared memory realm does not exist
Linux-x86_64 Error: 2: No such file or directory
Additional information: 3701
Additional information: -1145261241
Process ID: 0
Session ID: 0 Serial number: 0

為什麼 tns 不嘗試192.168.0.85

注意:我有一個靜態監聽器,可以嗎?如何解決?

有各種錯誤使 Oracle 客戶端考慮嘗試另一台主機。連接“AS SYSDBA”時的 SYS 使用者甚至可以連接到 MOUNTED 實例,因此沒有理由故障轉移到另一台主機。所以其他錯誤不被認為是那麼嚴重。“正確”的錯誤是:ORA-12505, TNS:listener does not currently know of SID given in connect descriptor. 當客戶端看到這一點時,它會嘗試連接到連接字元串中指定的另一個主機。

最簡單的方法(在您的情況下)是在一側安裝 RAC,在另一側安裝 Oracle Restart。

然後創建一個 SERVICE - 由集群件管理 - 僅在主端可用。

srvctl add service -db db_unique_name -service service_name -role PRIMARY
srvctl start service -db db_unique_name -service service_name 

需要注意的重要一點是,所選服務名稱不應是預設名稱之一。選擇一個像 dbname_app 這樣的名稱,以便清楚地表明該服務名稱是用於應用程序連接的。

然後嘗試使用dgmrgl並執行來啟動切換lsnrctl status。新創建的服務應僅在一個站點上線上。

如果您不使用 CRS,那麼有一些方法可以使用 TRIGGER ON DATABASE STARTUP 實現相同的方法。整個技巧是讓特定服務僅在一側可用。

您還應該將這些欄位添加到您的連接字元串中(作為範例添加的值)

TRANSPORT_CONNECT_TIMEOUT (5sec)
TIMEOUT (10s)
RETRY_COUNT ( 60x)

因此客戶端將不斷在兩側之間跳轉,嘗試連接,直到其中一側最終變為 PRIMARY。

PS:在這種情況下,JDBC 驅動程序的行為應該與 OCI 驅動程序完全相同。不幸的是,這不是真的。我真的建議在 Dataguard 中使用最新的 19c JDBC 驅動程序。

因為您有一個用於“jupiter”服務的靜態偵聽器條目。

當在偵聽器中找不到請求的服務時,會發生連接故障轉移。但是您的靜態註冊會破壞此功能,因為該服務將始​​終被找到,即使它後面沒有實例。

刪除您的靜態條目並使用基於角色的服務進行客戶端連接。

引用自:https://dba.stackexchange.com/questions/307228