Oracle

如何禁用 Oracle OCI 客戶端透明重新連接

  • November 14, 2020

我有一個我編寫的應用程序,它使用 OCI 連接到 Oracle 數據庫。該數據庫最近已升級到 Oracle 18,此後應用程序中的數據庫搜尋隨機停止工作。

我已將問題縮小到這個範圍。當應用程序連接到數據庫時,它會執行一些ALTER SESSION命令來禁用條件區分大小寫LIKE(這樣我就可以搜尋“smith”並仍然找到“Smith”)。幾個小時後,網路斷開 TCP 連接。第二天早上,當有人試圖訪問系統時,Oracle 客戶端透明地重新連接並執行查詢。

問題是這種重新連接是在我的程式碼不知道的情況下發生的,顯然是由 Oracle 客戶端本身進行的,並且在重新連接後它不會重新執行原始ALTER SESSION命令。我們的 DBA 向我提供了一個審計日誌,其中顯示了會話 ID 的變化、一次新的LOGON嘗試和一次ALTER SESSION設置時區的執行(這不是來自我的程式碼,也出現在原始連接中)。

這意味著我的應用程序正常向數據庫發出查詢,不知道有任何中斷,但突然它們變得區分大小寫並且使用者開始抱怨搜尋沒有返回任何結果。

對於以前的 Oracle 伺服器版本,如果我的程式碼已斷開連接,我的程式碼會收到錯誤,並且程式碼將嘗試重新連接,並且作為重新連接的一部分,它將ALTER SESSION再次執行命令,這樣系統的行為不會發生變化.

我找不到有關此自動重新連接功能或如何調整它的任何資訊,因此有什麼方法可以保留ALTER SESSION更改以便在重新連接後重新應用它們,或者禁用此行為並向程式碼返回錯誤如果連接像以前那樣失去?

客戶端是較舊的 11.2 版本,升級它並不實用,但由於它在伺服器升級之前工作,我會認為該版本可以。

似乎為您的連接啟用了透明應用程序故障轉移 (TAF)。如果啟用 TAF,如果客戶端和伺服器之間的連接中斷,Oracle 客戶端將重新連接到數據庫或備用數據庫。您使用 OCI 客戶端,為此可以註冊在客戶端重新連接後呼叫的 故障轉移回調函式 。在這個回調函式中,您可以發出您需要的“ALTER SESSION”命令。但也許你不想使用 TAF。

所以首先 DBA 應該檢查您的會話是否使用 TAF。可以在 Net Services Administrator’s Guide中找到適當的查詢

SELECT MACHINE, FAILOVER_TYPE, FAILOVER_METHOD, FAILED_OVER, COUNT(*)
FROM V$SESSION
GROUP BY MACHINE, FAILOVER_TYPE, FAILOVER_METHOD, FAILED_OVER;

使用以下範例輸出

MACHINE              FAILOVER_TYPE FAILOVER_METHOD FAILED_OVER   COUNT(*)
-------------------- ------------- ----------      ---           ----------
sales1               NONE          NONE            NO            11
sales2               SELECT        PRECONNECT      NO             1

FAILOVER_TYPE NONE 告訴我們,沒有配置 TAF。與 NONE 不同的 FAILOVER_TYPE 告訴我們為這些會話配置了 TAF。

如果您的會話使用 TAF,那麼您應該找出它的配置位置。它可以在客戶端或伺服器端進行配置。您可以檢查您的“tnsname.ora”文件或使用您的“tnsping”實用程序來檢查您的客戶端配置。如果您從Net Services Administrator’s Guide中找到與此範例類似 的內容

sales.us.example.com=
(DESCRIPTION=
 (LOAD_BALANCE=on) 
 (FAILOVER=on) 
 (ADDRESS=
      (PROTOCOL=tcp)  
      (HOST=sales1-server)  
      (PORT=1521)) 
 (ADDRESS=
      (PROTOCOL=tcp)  
      (HOST=sales2-server)  
      (PORT=1521)) 
 (CONNECT_DATA=
    (SERVICE_NAME=sales.us.example.com) 
    (FAILOVER_MODE=
      (TYPE=select) 
      (METHOD=basic))))

然後配置了 TAF,因為FAILOVER_MODE=(TYPE=select). 如果是這種情況,您應該配置一個不帶 TAF 的適當連接字元串。

但即使在客戶端沒有配置 TAF,它也可以在伺服器端配置此服務。所以做以下查詢

select NETWORK_NAME, FAILOVER_METHOD, FAILOVER_TYPE
from DBA_SERVICES
where NETWORK_NAME is not null;

(SERVICE_NAME=sales.us.example.com)以下範例輸出顯示即使未在客戶端上配置TAF,也將使用它。

NETWORK_NAME             FAILOVER_METHOD      FAILOVER_TYPE
------------------------ -------------------- --------------------
sales.us.example.com     BASIC                SELECT
sales3.us.example.com    NONE                 NONE

(SERVICE_NAME=sales.us.example.com)在這種情況下,即使客戶端上未配置TAF,也將使用TAF。因此,您必須使用沒有配置 TAF 的服務,例如“sales3.us.example.com”就是這樣的服務。

可以使用 DBMS_SERVICE 包創建服務,但在大多數情況下,它們是由一些附加工具創建的,例如 Oracle Real Application Cluster。通過在數據庫伺服器上執行以下命令,可以顯示 RAC 為數據庫“salesdb”創建的服務

srvctl config service -d salesdb

以下輸出(取決於數據庫版本)顯示 RAC 將在數據庫啟動後創建 TAF 服務

Service name: sales.us.example.com
Service is enabled
Server pool: SALESDB_sales.us.example.com
Cardinality: 2
Disconnect: false
Service role: PRIMARY
Management policy: AUTOMATIC
DTP transaction: false
AQ HA notifications: false
Failover type: SELECT
Failover method: BASIC
TAF failover retries: 5
TAF failover delay: 2
Connection Load Balancing Goal: LONG
Runtime Load Balancing Goal: NONE
TAF policy specification: BASIC
Edition:
Preferred instances: sales2-server,sales2-server
Available instances:
Service is enabled on instances: SALESDB1,SALESDB2

您可以使用以下命令在沒有 TAF 的情況下創建新服務“sales3.us.example.com”

srvctl add service -d salsedb -s sales3.us.example.com

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