如何禁用 Oracle OCI 客戶端透明重新連接
我有一個我編寫的應用程序,它使用 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