天天看點

Oracle RAC 11gR2 環境下的連接配接管理

這篇文章詳細介紹了Oracle RAC環境下的連接配接管理,分别介紹了什麼是 Connect Time Load Balancing、Runtime Connection Load Balancing、Connect Time Connection Failover 和 Runtime Connection Failover,以及裡面所涉及到的 TAF、ONS、FCF、FAN、LBA 等諸多知識點。本文主要是針對 Oracle RAC 11gR2 環境下的連接配接管理,但同時也會對比說明一下 Oracle RAC 10gR2/9iR2,以展現他們之間在連接配接管理上的差異。

所謂“連接配接管理”,主要展現在 Load Balancing 和 Failover 兩方面。Oracle RAC 11gR2 下的 Load Balancing 和 Failover,根據是否使用了事先已經存在的連接配接(如連接配接池中的連接配接)又分為 Connect Time Load Balancing、Runtime Connection Load Balancing、Connect Time Connection Failover和Runtime ConnectionFailover 這 4 種類型,凡是帶上了“Runtime”字首的,就是指連接配接已經存在的情況,比如使用了連接配接池。

一、首先來介紹 Connect Time Connection Failover

Connect Time Connection Failover 是指不從連接配接池中取得已有連接配接,而是直接連接配接 Oracle 資料庫時的 Failover。在 Oracle RAC 11gR2 之前,Connect Time Connection Failover 是非常容易實作的,隻需要在相關的 tnsnames.ora 中指定多個 vip,同時指定 FAILOVER=ON 就好了。如下所示:

(DESCRIPTION=

(FAILOVER=ON)

(ADDRESS_LIST=

(LOAD_BALANCE=OFF)

(ADDRESS=(PROTOCOL=TCP)(HOST=RAC1-vip)(PORT=1521))

(ADDRESS=(PROTOCOL=TCP)(HOST=RAC2-vip)(PORT=1521))

(ADDRESS=(PROTOCOL=TCP)(HOST=RAC3-vip)(PORT=1521))

(ADDRESS=(PROTOCOL=TCP)(HOST=RAC4-vip)(PORT=1521))

)

(CONNECT_DATA=(SERVICE_NAME=RAC10g))

)

這裡用戶端程序首先會嘗試連接配接 RAC1-vip,如果連不上,則會嘗試RAC2-vip,再連不上,則會繼續往下嘗試,直到所有出現在 ADDRESS_LIST 中的 vip 位址全部順序嘗試完為止。這種用戶端在連接配接 Oracle 資料庫時的 Failover,不僅适用于 RAC 環境,也适用于 Data Guard 環境。如下所示:

DESCRIPTION=

(FAILOVER=ON)

(ADDRESS_LIST=

(LOAD_BALANCE=OFF)

(ADDRESS=(PROTOCOL=TCP)(HOST=primary-ip)(PORT=1521))

(ADDRESS=(PROTOCOL=TCP)(HOST=standby-ip)(PORT=1521))

)

(CONNECT_DATA=(SERVICE_NAME=service10g))

)

Oracle RAC 11gR2 引入了 SCAN(Single Client Access Name),并且用戶端預設是通過 SCAN 來連接配接整個 RAC 環境的,如下是 SCAN 的架構圖:

Oracle RAC 11gR2 環境下的連接配接管理

如上圖所示,如果使用了 DNS 或者 GNS (Grid Naming Service),那麼最多可以有 3 個 SCAN VIP 和 3 個 SCAN Listener;如果沒有使用 DNS 或者 GNS,而是選擇使用 hosts 檔案,則隻會有 1 個 SCAN VIP 和 1 個 SCAN Listener。

這裡假設在 tnsnames.ora 中這樣配置:

(DESCRIPTION =

(FAILOVER=ON)

(ADDRESS = (PROTOCOL = TCP)(HOST = MySCAN)(PORT = 1521))

(CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME =RAC11g)))

嚴格意義上說,隻有在 RAC 環境有 1 個以上 SCAN VIP 的時候,上述 FAILOVER=ON 才有意義——它表示的是用戶端在連接配接 SCAN VIP 的時候,如果其中的一個 SCAN VIP 連不上,則馬上會嘗試另外一個 SCAN VIP。

當使用了 hosts 檔案來指定 SCAN VIP 的時候,即在整個 RAC 環境隻有 1 個 SCAN VIP 的情況下,Failover 其實也存在,隻不過這種情況下 Failover 的速度會慢一些。因為當 SCAN VIP 所在的節點宕掉後,SCAN VIP 會和相關的 SCAN Listener 一起整體 Failover 到其他節點,隻不過這個 Failover 需要時間,而用戶端需要等待這個 Failover 過程完畢後才能重新連上 RAC。

二、接下來介紹 Runtime Connection Failover

Runtime Connection Failover 是指連接配接已經存在的情況下的 Failover。這個已存在的連接配接,可能是連接配接池中正在用的連接配接,也可能是不通過連接配接池、直接通過 OCI 用戶端(如 sqlplus)連上 Oracle 資料庫後的連接配接。

這種 Runtime Connection Failover,就是指在連接配接已經存在的情況下,如果 Oracle 資料庫端出現了異常的情況(比如 Service 宕了、Instance 崩潰了、Session 斷了)而導緻已有連接配接中斷,怎樣 Failover 的問題。

有兩種手段來實作 Runtime Connection Failover,分别為 TAF(Transparent Application Failover)和 FCF(Fast Connection Failover)。

首先來介紹 TAF。TAF 有如下一些知識點需要我們注意:

1、它可以在 client 端的 tnsnames.ora 中的連接配接串裡定義,也可以在 server 端的 service 中定義,隻不過 service 端的設定會取代(override)用戶端 tnsnames.ora 中的設定:

用戶端可以這樣設定 TAF:

(DESCRIPTION =

(FAILOVER=ON)

(ADDRESS = (PROTOCOL = TCP)(HOST = MySCAN)(PORT = 1521))

(CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = Email)

(FAILOVER_MODE= (TYPE=select)(METHOD=basic)(RETRIES=180)(DELAY=5)))

Server 端可以這樣設定 TAF:

srvctl modify service -d RAC11g -s Email -q TRUE -P BASIC -e SELECT -z 180 -w 5 -j LONG 具體各個參數的含義可參見如下注釋:

Usage: srvctl modify service -d <db_unique_name> -s <service_name> [-c {UNIFORM |

SINGLETON}] [-P {BASIC|PRECONNECT|NONE}] [-l

[PRIMARY][,PHYSICAL_STANDBY][,LOGICAL_STANDBY][,SNAPSHOT_STANDBY]] [-y

{AUTOMATIC | MANUAL}][-q {true|false}] [-x {true|false}] [-j {SHORT|LONG}] [-B

{NONE|SERVICE_TIME|THROUGHPUT}] [-e {NONE|SESSION|SELECT}] [-m

{NONE|BASIC}] [-z <integer>] [-w <integer>]

-d <db_unique_name> Unique name for the database

-s <service> Service name

-c {UNIFORM | SINGLETON} Service runs on every active server in the server

pool hosting this service (UNIFORM) or just one server (SINGLETON)

-P {NONE | BASIC | PRECONNECT} TAF policy specification

-l <role> Role of the service (primary, physical_standby,

logical_standby, snapshot_standby)

-y <policy> Management policy for the service (AUTOMATIC or MANUAL)

-e <Failover type> Failover type (NONE, SESSION, or SELECT)

-m <Failover method> Failover method (NONE or BASIC)

-w <integer> Failover delay

-z <integer> Failover retries

-j <clb_goal> Connection Load Balancing Goal (SHORT or LONG). Default is LONG.

-B <Runtime Load Balancing Goal> Runtime Load Balancing Goal (SERVICE_TIME,

THROUGHPUT, or NONE)

-x <Distributed Transaction Processing> Distributed Transaction Processing (TRUE or FALSE)

-q <AQ HA notifications> AQ HA notifications

(TRUE or FALSE)

-h Print usage

2、當 TAF 的TYPE 設定為 select 的時候,單純 select 操作(不包括 select … for update)可以做到“斷點續傳”,即單純的 select 操作在利用 TAF 實作 Failover 後是可以從中斷的地方繼續往下執行的;

3、TAF 對 DML 操作不能做到“斷點續傳”,即如果一個 transaction 在使用 TAF 實作 Failover 後,該 transaction 不能從中斷的地方繼續執行,需要再次從頭開始執行;

4、TAF 僅對使用 OCI 連接配接的用戶端和連接配接池有效,這裡的 OCI 連接配接可以是在 OCI 連接配接上的封裝,比如 JDBC-OCI driver 就支援 TAF,但 JDBC thin driver 就不支援 TAF(因為 JDBC thin driver 不是基于 OCI 的)。

接下來,在介紹 FCF(Fast Connection Failover)之前,我們必須要先介紹 FAN(Fast Application Notification)。

FAN 是 Oracle RAC 裡的一種消息主動通知機制。當 RAC 裡出現 service down/up,instance down/up,節點負載變化時,Oracle 資料庫都能通過 FAN events 将這些資訊釋出出去,訂閱這些 FAN events 的用戶端在第一時間收到這些 FAN events 後就能做出相應的動作來響應這些 FAN events。

FAN events 分為兩種,第一種是 FAN HA events,第二種是 LBA events,這裡的 LBA 是指 Load Balancing Advisory。

當 RAC 裡出現 service down/up、instance down/up 時就會觸發 FAN HA events。FAN HA events 的示例如下所示:

Event 1: FAN event type: instance

Properties: version=1.0 service=PROD database=PROD instance=PROD1 host=node1 status=down

Event 2: FAN event type: service_member

Properties: version=1.0 service=ERP database=PROD instance=PROD1 host=node1 status=down

Event 3: FAN event type: service_member

Properties: version=1.0 service=ERP database=PROD instance=PROD3 host=node3 status=up

RAC 裡節點的負載變化後也會産生 LBA events,LBA events 的示例如下所示:

Event 4: FAN-event type: service_metrics

Properties: version=2.0 service=ERP database=PROD instance=PROD1 percent=70

service_quality=GOOD instance=PROD2 percent=30 service_quality=GOOD

Event 5 :FAN-event type: service_metrics

Properties: version=2.0 service=CRM database=PROD instance=PROD2 percent=30

service_quality=GOOD instance=PROD3 percent=70 service_quality=GOOD

上述 FAN events 可能會通過多種管道傳播出去,這些管道包括 ONS(Oracle Notification Service),AQ(Advanced Queue),PMON 等。下面是關于 FAN events 架構和傳播途徑的兩張圖,它們就直覺的說明了 FAN events 的傳播途徑:

Oracle RAC 11gR2 環境下的連接配接管理
Oracle RAC 11gR2 環境下的連接配接管理

訂閱 FAN HA events 的用戶端包括:JDBC Implicit Connection Cache, OCI, ODP.NET Connection Pools, Listener, Server Side Callouts 等;

訂閱 LBA events 的用戶端包括:JDBC Implicit Connection Cache, ODP.NET Connection Pools, Listener,OCI Session Pools 等;

介紹完 FAN,現在可以開始介紹 FCF:FCF 的意思是 Fast Connection Failover,它實際上是用戶端通過訂閱 FAN HA events 來實作的。如下是兩個用戶端通過訂閱 FAN HA events 來實作 FCF 的例子:

例一:JDBC Fast Connection Failover (FCF)

這裡的 JDBC 連接配接是指 JDBC thin 連接配接。因為 JDBC thin 連接配接不是基于 OCI 的,是以這種情況下的 Runtime Connection Failover 不能使用 TAF,隻能用 FCF。并且要做如下幾件事情後才可以正常使用 FCF:

1、把 implicit connection cache 打開;

2、把 FastConnectionFailoverEnabled 打開;

3、最好是直接訂閱遠端的 ONS(在Oracle 10gR2 之前的版本不能直接訂閱遠端的 ONS,隻能通過在本地安裝 ONS 後來實作 FAN events 的中轉);

4、最好是在 Java 程式裡設定一下 TCP timeout(後面專門會講到在 Oracle 資料庫裡如何調整 TCP timeout);

示範代碼如下:

OracleDataSource ods = new OracleDataSource()

ods.setUser(“Scott”)

ods.setPassword(“tiger”)

ods.setConnectionCachingEnabled(true);

ods.setFastConnectionFailoverEnabled(true);

ods.setConnectionCacheName(“MyCache”)

ods.setConnectionCacheProperties(cp);

ods.setONSConfiguration(“nodes=racnode1:6201,racnode2.:6201″);

ods.setURL(“jdbc:oracle:thin:@sales1-scan:1521/oltp”);

//TCP connect timeout

Properties prop = new Properties();

prop.setProperty(“MinLimit”, MIN_CONN);

prop.setProperty(“MaxLimit”, MAX_CONN);

prop.setProperty(“InitialLimit”, INIT_CONN);

prop.put (oracle.net.ns.SQLnetDef.TCP_CONNTIMEOUT_STR, “1000″)); //

這裡是表示把TCP timeout設為1000毫秒,即1秒

ods.setConnectionCacheProperties(prop);

例二:ODP.NET Fast Connection Failover (FCF)

對于 ODP.NET 而言,通常做了如下幾件事情後就可以使用 FCF 了:

1、把對應 service 的 AQ Notification 打開:

srvctl modify service -d RAC11g -s Email -q TRUE

2、把 aq_tm_processes 的值設為 1;

3、賦予指定使用者 de-queue 的權限:

exec dbms_aqadm.grant_queue_privilege(‘DEQUEUE’,'SYS.SYS$SERVICE_METRICS’, <your username=>);

4、在 .NET 連接配接串裡設定 HA events=true;

示範代碼如下:

// C#

using System;

using Oracle.DataAccess.Client;

class ConnectionPoolingSample

{

static void Main()

{

OracleConnection con = new OracleConnection();

//Open a connection using ConnectionString attributes

//related to connection pooling.

con.ConnectionString =

“User Id=scott;Password=tiger;Data Source=crm;” +

“Min Pool Size=10;Connection Lifetime=120;Connection Timeout=60;” +

“HA events=true”, “Incr Pool Size=5; Decr Pool Si=2″;

con.Open();

Console.WriteLine(“Connection pool successfully created”);

// Close and Dispose OracleConnection object

con.Close();

con.Dispose();

Console.WriteLine(“Connection is placed back into the pool.”);

}

}

FCF 跟 TAF 有一個很大的不同就是即便是單純 select 操作,FCF 也不能像 TAF 那樣做到“斷點續傳”。對于配置好了 FCF 的連接配接池而言,當它接收到包含 instance/service 宕掉的 FAN HA events 後,原先 cache 在連接配接池裡的跟這個 instance/service 相關的連接配接馬上會被标記為失效(invalid)同時這些連接配接會被清除,使用這些連接配接的 transaction 也會馬上中止并復原。當應用捕捉到這個中止的 transaction 所産生的錯誤資訊後,要麼直接把相關錯誤傳回給最終使用者,要麼從連接配接池中重新取得一個有效連接配接并重新執行這個被中止的 transaction。

在啟用了 FCF 的情況下,如果連接配接錯誤被傳回給了最終使用者,那麼應該如何判斷錯誤資訊的來源呢(即是否是 FCF 傳回的錯誤)?很簡單,用 isFatalConnectionError(SQLException e)來判斷一下就好了,示範代碼如下:

try {

conn = getConnection();

//這裡取得連接配接後做相關的工作

} catch (SQLException e) {

handleSQLException(e)

}

void handleSQLException (SQLException e)

{

if

(OracleConnectionCacheManager.isFatalConnectionError(e))

ConnRetry = true; //這裡表示捕捉到FCF傳回的錯誤

}

三、接着介紹 Connect Time Load Balancing

繼續閱讀