為什麼 tnsnames 不能正確故障轉移到備用數據庫?
我有這個 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 db
rac-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”服務的靜態偵聽器條目。
當在偵聽器中找不到請求的服務時,會發生連接故障轉移。但是您的靜態註冊會破壞此功能,因為該服務將始終被找到,即使它後面沒有實例。
刪除您的靜態條目並使用基於角色的服務進行客戶端連接。