TAF – Connection Failover options
전제 사항 : Oracle Server는 RAC로 구성되어야 한다.
OCI를 이용하지 않은 Application은 TAF를 위한 특별한 기능을 제공 하지 않으며, 개발자가 Logic을 구현해야 한다.
TAF를 위한 Server Configuration은 이 문서에서 고려하지 않는다. CONNECTION TIME FAIL OVER는 이 문서에서 고려하지 않는다. 위의 사항들을 시간의 여유가 있을 경우에는 작성한다.
TAF는 RAC를 사용하는 환경에서 가용성을 극대화 하기 위해 제공 되는 기능이며, 모든 Application을 적용하기 보다는 중요한 Application에 대해서만 적용토록 한다.
TAF 적용시 고려 사항들
구 분 |
내 용 |
고려사항 |
CTF(Connection Time FailOver) |
데이터 베이스로 접속하는 순간에 Server, DB, Listener등이 가용하 지 않을 경우에 다른 쪽 Server로 접속하는 것을 말함. |
OCI를 사용하지 않는 프로그램은 매뉴얼 하게 Logic를 구사해야 한다. |
TAF(Run Time FailOver) |
접속 후 데이터 베이스 사용 중에 DB나 Session이 장애가 발생 했 을 경우에 다른 node로 접속하여 진행하던 작업을 계속할 수 있도 록 하는 것을 말함. |
OCI를 사용할 경우에는 오라클에서 CallBack method를지 원하나 OCI를 사용하지 않을 경우에는 Logic으로 구사해야 함 |
FailOver 방법 |
TAF에서 제공하는 Failover 방법들을 말함. Mode : session, select Method : Basic , Preconnect |
Long s elect수행중 장애 발생시 수행하던 작업을 넘기기 위해서는 ‘s elect’로 해야 하며 ‘session’으로 하면 session 만 넘어가고 SQL은 다시 수행해야 함. Basic은 장애 발생시 다시 접속하는 방법이고, preconnect는 최초 접속시 다른 node에 미리 |
Language 별 |
모든 programming language 를 TAF가 지원하지는 않고 OCI를사용하는 language 만을 지원 한다. |
OCI를 사용하지 않는 Language 의 경우에는 자체적으로 Logic으로 처리해 한다. Ex) java thin driver사용시 |
장애 유형별 사용 여부 |
장애 유형별 TAF를 사용해야 할지 결정한다. |
여러 가지 장애에 따라, TAF를 사용할 Error와 사용하지않 을 Error를 구분하여 적용해야 함. |
적용할 Application 선정 |
위의 내역들을 모두 고려하여 CTF, TAF를 적용한 Application을선 정한다. 이때 너무 많은 Application을 고려 할 경우에는 상황의 복 잡함에 시스템의 안정화에 나쁜 영향을 줄 수 있다. |
프로그램의 중요도에 따라 CTF, TAF를 적용할 Application 을 선정하며, 다양한 Error에 대한 조치사항을 적절하게 적용해야 한다. |
TAF에는 여러 가지 mode 및 method가 있는데, 각 Application에 적합한 TAF방법을 결정한다.
Method/ Mod |
SESSION |
SELECT |
BASIC |
장애 발생시 client는 자동적으로 다른 node로 Login이 된다. 만약 수행하던 Select문이 있을 경우 에는 다시 수행해야 한다. |
Query를 수행하는 동안 장애가 발생하면 자동으로 다른 node로 Log in이 되며, 수행하던 Query를 자동으로 다시 수행하게 된다. |
PRECONNECT |
Client는 접속 시 2개의 node에 모두 접속한다. 이러한 방식은 장애 발생시 접속의 부하를 줄일 수 있다. 물로 양쪽 node에 접속하고 있으므로 접속에 대한 부담 이 존재한다. |
Client는 접속 시 2개의 node에 모두 접속한다. |
제약사항 :OCI(NET8)을 사용하는 Application에 한 해서 적용가능 하다.
만약 OCI를 사용하지 않는 Application은 Manual하게 조치해야 함. 성능 측면에서 Application Partitioning후에 TAF로 Failover는 RAC의 부담을 줄 수 있으므로 이에 대한 고려도 필요함(ping의 부하)
TAF Application 선택 기준
적용 여부 |
Application의 성격 |
TAF 적용 |
24X365로 수행되는 Application(daemon 형태의 프로그램으로 자체적으로 재기동 할 수 없는Application) |
중요 Transaction을 포함하는 Application |
|
TAF 미적용 |
단순 조회 Web Application |
C/ S 환경의 조회 Application |
|
다시 시작해도 되는 Transaction을 가진 Application |
Application TAF 적용 단계 Flow
개발 언어에 따른 TAF 사용 여부
Java, C++, etc
TAF를 사용 가능한 Client Application Product
Product |
구분 |
Oracle Call Inte rface |
Release 8 |
ODBC driver |
Release 8.0.5 |
JDBC driver |
Release 8 (thick driver only) |
Pro*C |
Release 8i |
SQL*Plus |
Release 8.0.4 |
Oracle Object for OLE |
Release 8i(Planned) |
특수한 사용 형태에 따른 고려사항.
Java의 Connection Pool 형태의 Connection에 대한 TAF 구현방법 모색.
OCI를 사용하지 않는 Application 은 자체적으로 Error를 탐지 하여 프로그램 내에 서 Logic으로 처리하여야 한다.
-
장애 발생 시점 시나리오
장애의 유형에 따라 TAF를 사용하는 경우와 사용하지 않는 경우를 구분하여 나누어 고려한다.
Error 번호 |
Error 내용 |
|
사용중 장애(TAF 함) |
ORA- 01034 ORA- 3113, ORA- 3114 ORA- 1033 ORA- 25401 ORA- 00020 |
Oracle Not Available Instance Down Shutdown progress Cannot Continue Fetch(Fetch 중 Error) Maximum number of processes xx exceeded |
접속 시 장애(CTF 함) |
ORA- 12541 ORA- 01034 |
TNS:nolis tener Oracle Not Available |
일반 Error(TAF하지 않음) |
Others |
일반 SQL수행시 발생하는 Error는 TAF에 적용하지 않는다. Ex) extent error나 unique violation error등. |
장애의 복구를 위한 시도에 대한 제한(예, 10회)을 두어 장기적인 장애시 불필요한 자원 낭비를 예방한다.
FailOver(TAF)의 경우에 아래의 몇 가지 정보들을 잃어버리게 되므로, TAF를 적용하기로선정 된 Application내에서 잃어버린 정보에 대한 처리 Logic을 넣어야 한다.
FailOver될 때, RAC환경 의 Global Loc에 대한 remastering 작업으로 약간의 지체 현상이 나타날 수 있다.
종 류 |
내 용 |
PL/ SQL Pac kage s tatus |
Package 의 global 변수 같은 정보는 손실됨 |
Alter Sess ion Statement |
Alter s ess ion을 이용한 작업은 손실 되며, 이는 TAF후에 다시 적용하여수 행 해야 한다. |
진행중인 Trans action |
Trans action은 반드시 rollbac k한후 작업을 진행할수 있다. |
Cursor |
Cursor를 열고 연속적인 작업을 하는 것은 e rro r를 발생할수 있다. (ora- 25401) |
Temporary table data |
Temporary table을 사용하는 정보는 잃어버린다. |
Lob loc ator reads |
OCI를 사용하는 경우의 CTF
OCI 없이 CTF 구현
OCI를 사용하는 경우의 TAF
OCI 없이 TAF 구현
TAF Sample 프로그램
Test환경 환경 Server : THVSD01, THVSD02
Java : Thick(OCI에서 제공되는 callback이용), Thin(Logic으로 처리)
User : oraerp01
Listener.ora 내역 내역
listener.ora(node 1)
ERP01 =
(ADDRESS_LIST =
(ADDRESS= (PROTOCOL= IPC)(KEY= EXTPROCERP01))
(ADDRESS= (PROTOCOL= TCP)(Host= td01_net)(Port= 1812)) )
listener.ora(node 2)
ERP02 =
(ADDRESS_LIST =
(ADDRESS= (PROTOCOL= IPC)(KEY= EXTPROCERP01))
(ADDRESS= (PROTOCOL= TCP)(Host= td02_net)(Port= 1812)) )
Tnsnames.ora
TAF_ERP01=
(DESCRIPTION_LIST=
(DESCRIPTION=
(FAILOVER=on)
(ADDRESS_LIST =
(ADDRESS=(PROTOCOL=tcp)(HOST=TD01_net) (PORT=1812))
(ADDRESS=(PROTOCOL=tcp)(HOST=TD02_net) (PORT=1812))
)
(CONNECT_DATA=
(SERVICE_NAME=ERP)
(FAILOVER_MODE=
(BACKUP=TAF_ERP01)
(TYPE=SELECT)
(METHOD=BASIC)
) ) )
)
TAFwithOCI.java Sample
//OCI 를 이용한 Sample로 로써 써 CallBack Class 를 이용하여 처리한다.
// You need to import java.sql and oracle.jdbc packages to use
// JDBC OCI failover callback
import java.sql.*;
import java.net.*;
import java.io.*;
import java.util.*;
import oracle.jdbc.OracleConnection;
import oracle.jdbc.OracleOCIFailover;
public class TAFwithOCI {
static final String user = “scott”;
static final String password = “tiger”;
static final String driver_class = “oracle.jdbc.driver.OracleDriver”;
static final String URL = “jdbc:oracle:oci8:@TAF_ERP01”;
public static void main (String[] args) throws Exception {
Connection conn = null;
CallBack fcbk= new CallBack();
String msg = null;
Statement stmt = null;
ResultSet rset = null;
// Load JDBC driver
try {
Class.forName(driver_class);
}
catch(Exception e) {
System.out.println(e);
}
// Connect to the database
conn = DriverManager.getConnection(URL, user, password);
// register TAF callback function
((OracleConnection) conn).registerTAFCallback(fcbk, msg);
// Create a Statement
stmt = conn.createStatement ();
for (int i=0; i<30; i++) {
// Select the ENAME column from the EMP table
rset = stmt.executeQuery (” select to_char(sysdate,’YYYY MM DD HH24:MI:SS’)|| ” +
” ‘[‘||instance_name||’][‘||host_name||’]’ from v$instance “);
TAFwithOCI.java Sample
// Iterate through the result and print the employee names
while (rset.next ())
System.out.println (rset.getString (1));
// Sleep one second to make it possible to shutdown the DB.
Thread.sleep(1000);
} // End for
rset.close();
stmt.close();
conn.close();
} // End Main()
} // End class jdemofo
/* * Define class CallBack */
class CallBack implements OracleOCIFailover {
// TAF callback function
public int callbackFn (Connection conn, Object ctxt, int type, int event) {
/*********************************************************************
* There are 7 possible failover event
* FO_BEGIN = 1 indicates that failover has detected a
* lost conenction and faiover is starting.
* FO_END = 2 indicates successful completion of failover.
* FO_ABORt = 3 indicates that failover was unsuccessful,
* and there is no option of retrying.
* FO_REAUTH = 4 indicates that a user handle has been re-
* authenticated.
* FO_ERROR = 5 indicates that failover was temporarily un-
* successful, but it gives the apps the opp-
* ortunity to handle the error and retry failover.
* The usual method of error handling is to issue
* sleep() and retry by returning the value FO_RETRY
* FO_RETRY = 6
* FO_EVENT_UNKNOWN = 7 It is a bad failover event
*********************************************************************/
String failover_type = null;
switch (type) {
case FO_SESSION:
failover_type = “SESSION”;
break;
case FO_SELECT:
failover_type = “SELECT”;
break;
default:
failover_type = “NONE”;
}
switch (event) {
case FO_BEGIN:
System.out.println(ctxt + “: “+ failover_type + ” failing over…”);
break;
case FO_END:
System.out.println(ctxt + “: failover ended”);
break;
case FO_ABORT:
System.out.println(ctxt + “: failover aborted.”);
break;
case FO_REAUTH:
System.out.println(ctxt + “: failover.”);
break;
case FO_ERROR:
System.out.println(ctxt + “: failover error gotten. Sleeping…”);
// Sleep for a while
try {
Thread.sleep(100);
}
catch (InterruptedException e) {
System.out.println(“Thread.sleep has problem: ” + e.toString());
}
return FO_RETRY;
default:
System.out.println(ctxt + “: bad failover event.”);
break;
}
return 0;
}
}
TAFwithLogic.java Sample
// 장애에 대한 처리를 Application 에서 Logic으로 처리한다 으로 처리한다
import java.io.*;
import java.util.*;
import java.sql.*;
import java.text.*;
public class TAFwithLogic
{
public static void main( String[] args ) throws Exception
{
DriverManager.registerDriver( new oracle.jdbc.driver.OracleDriver() );
Connection conn = null;
Statement stmt = null;
//while ( true )
for(int i = 1; i < 100; i++)
{
if ( conn == null )
try
{
conn = DriverManager.getConnection( “jdbc:oracle:oci8:@TAF_ERP01”, “apps”, “apps” );
System.out.println ( “[” + DateFormat.getDateTimeInstance().format( new java.util.Date() ) +
“] Connection Success” );
}
catch ( SQLException e )
{
System.out.println ( “[” +
DateFormat.getDateTimeInstance().format( new java.util.Date() ) + “] Connect FAIL!!” );
System.out.println( e );
Thread.sleep( 1000 );
continue;
}
try
{
stmt = conn.createStatement();
//ResultSet rs = stmt.executeQuery( “select sid froM v$session” );
ResultSet rs = stmt.executeQuery(
” select to_char(sysdate,’YYYY MM DD HH24:MI:SS’)|| ” +
” ‘[‘||instance_name||’][‘||host_name||’]’ from v$instance ” );
rs.next();
System.out.println(rs.getString(1));
stmt.close();
Thread.sleep( 1000 ); // wait 1 second
}
catch ( SQLException e ) // SQL 수행중에 Error가 발생하 가 발생하 면 다시 접속한다 한다.
{
System.out.println ( “[” +
DateFormat.getDateTimeInstance().format( new java.util.Date() ) + “] Select FAIL!!” );
System.out.println( e );
conn = null;
}
}
}
}