Tuesday, March 25, 2014

Oracle RAC 11.2 Server Pools


Server Pools

There is nothing unusual with 11.2 server pools, but when it comes to nested pools there are some unexpected glitches. First, it looks like the standard "srvctl" command doesn't support nested server pools at all (as of version 11.2) - if you want a nested pool, you have to modify its attribute with crsctl. After you change a pool with crsctl you won't be even able to read its configuration using srvctl anymore.

Lets create a nested server pool:

$ srvctl add srvpool -g avif -l 1 -u 3 -n "lab241"
$ srvctl status srvpool -g avif -a
 
$ crsctl status serverpool -f

$ srvctl add srvpool -g avifapp -l 1 -u 2
$ srvctl add srvpool -g avifbat -l 1 -u 1 -i 100

$ crsctl modify srvpool ora.avifapp -attr "PARENT_POOLS=ora.avif"
$ crsctl modify srvpool ora.avifapp -attr "IMPORTANCE=200"
$ crsctl modify srvpool ora.avifbat -attr "PARENT_POOLS=ora.avif"
$ crsctl status serverpool ora.avifapp -f
 
$ crsctl modify srvpool ora.avifbat -attr "PARENT_POOLS="
$ crsctl modify srvpool ora.avifapp -attr "PARENT_POOLS="
 
Srvctl seems to be completely confused when you alter the configuration of pools with crsctl. Adding a nested pool to a pool makes it invisible to srvctl, you cannnot even start up an instance using srvctl. When you query the database's config, it shows the database is admin managed - despite the fact previously it was policy managed. So it is all messed up.

Bugs

$ crsctl modify srvpool ora.avifapp -attr "EXCLUSIVE_POOLS=AVIF"
CRS-2596: Modifications to the 'EXCLUSIVE_POOLS' attribute of
          server pools are not supported
CRS-4000: Command Modify failed, or completed with errors.

$ srvctl modify srvpool -g avifapp -i 200
PRKO-3130 : Server pool avifapp is internally managed as part of
            administrator-managed database configuration and
            therefore cannot be modified directly via srvpool object. 
 
Today's comment of MOS (26 March 2014): It is not supported to modify the value of EXCLUSIVE_POOLS to some string.

Resources

  1. Server Pools Attributes (11.2)
  2. A blog article about Server Pools (11.2) with some interesting bug catches.

Saturday, February 15, 2014

National Characterset for Ubuntu Console

About Locales

It is not an in-depth guide but rather a briefing which I used to write down the most essential things about customizing locales.
Despite the post is focused on Polish locale, you might find it helpful because the procedure is similar for other languages.

Steps

Install possible missing packages. In the new Ubuntu release it is as simple as:

aptitude install language-pack-pl

Which automatically generates appropriate locales.

In older Ubuntu versions:

   aptitude install locale
   aptitude install localedef

lenny: apt-cache install locales-all

 X11

After "locale/language-pack" packages are installed and assuming proper fonts are already here, national characters should be visible without any issue in xterm and similar applications. However it still needs a proper keyboard layout.

For Redhat (Oracle Enterprise Linux) 6.4 it is as simple as going to System -> Preferences -> Keyboard -> Layouts and choosing Polish (or other) layout there, optionally making it the default one.

For Ubuntu 13.10: System Settings -> Text Entry -> Input source to use: pick your national keyboard here, make it default if you prefer.

Console Specific

vim /etc/default/console-setup:

CHARMAP=UTF-8
CODESET=Uni2
XKBLAYOUT=pl (can be in /etc/default/keyboard)

setupcon -v

Locale General

  1. locale (examines standard environment settings for locales)
  2. locale -a (examines what choices are possible)
  3. If there is not Polish locales: locale-gen pl_PL.UTF8 (checkout /etc/locale.gen)
  4. Files:
    • /etc/default/locale - global system locale definition
    • /etc/environment

References

  1. Ubuntu Locale Help

Thursday, February 13, 2014

Ubuntu freezing packages

Recently I decided to move my desktop environment to the latest Ubuntu 13 (Saucy) to gain the latest packages:

root@ubuntu13:~# cat /etc/lsb-release 
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=13.10
DISTRIB_CODENAME=saucy
DISTRIB_DESCRIPTION="Ubuntu 13.10"
root@ubuntu13:~#

This is not LTS (long term) and it gets its packages updated very often.
From the other side - I'm running it through Oracle VirtualBox and I'm sick of recompiling modules each time the kernel gets updated. Having VirtualBox modules not aligned with the kernel (guest additions) means I'm loosing auto-resize guest display, cannot mount host filesystems and cannot use shared clipboard.

So I need simply ignore updates for a set of packages. And starting with Ubuntu 12 there is a possiblity to mark the packaged on hold. Here is what is enough to gain the goal:

apt-mark hold linux-generic
apt-mark hold linux-firmware
apt-mark hold linux-image-\*
apt-mark hold linux-headers-\*

apt-mark showhold
Nice!

  1. Ubuntu Pinning Howto

Monday, February 3, 2014

Oracle TIMESTAMP and TIMEZONE

TIMESTAMP

The "Timestamp" datatype has no concept of timezones, it's basically the same as the "date" dataype but with added precision.


select * from scott.emp
where to_timestamp(hiredate) = TIMESTAMP'2003-04-07 00:00:00 CET';

TIMEZONE

Oracle has 2 datatypes who can store timezones: TimeStamp with Time Zone (TSTZ) and TimeStamp with Local Time Zone (TSLTZ).

TimeStamp with Time Zone (TSTZ) data stores the time and the actual timezone offset/name used for that time at the moment of insert. The stored timezone information can be an offset or named timezone. The date format for TIMESTAMP WITH TIME ZONE is determined by the value of the NLS_TIMESTAMP_TZ_FORMAT parameter.



TimeStamp with Local Time Zone (TSLTZ) data stores internally the time converted to/from the database timezone (see point 3) from the timezone specified at insert/select time.
Note that the data stored in the database is normalized to the database time zone, and the time zone offset is not stored as part of the column data, the current DBTIMZONE is used. When users retrieve the data, Oracle Database returns it in the users' local session time zone from the current DBTIMEZONE.
The date format for TIMESTAMP WITH LOCAL TIME ZONE is determined by the value of the NLS_TIMESTAMP_FORMAT parameter. TIMESTAMP WITH LOCAL TIME ZONE data is NOT returned with a timezone in the result set.

If you store TSLTZ data the database timezone should always be an offset.

Note that the SESSIONTIMEZONE (and NOT the database timezone) is the actual used timezone at both insert and select (if not specified explicit) to calculate the time for the inserted/returned result.

 

What is the difference between a timezone offset and a named timezone?

A timezone expressed in a offset (example: -04:00) is always the same and gives the difference compared to UTC (Coordinated Universal Time), practically (although not correct technically speaking) UTC is the same as GMT (Greenwich mean time), and UTC/GMT corresponds to a offset of +00:00.

Because a offset is fixed it cannot change reflect DST (Daylight Saving Time) changes. DST itself is a change of the offset.

A named timezone is a name (example: Canada/Eastern or GMT) who reflects a geographic region or location and this will be mapped to a certain offset for a certain time on a certain date. The offset may or may not change for DST or have been changed during history.

The named timezone Europe/London for example will have a different offset during summer (+01:00) as during winter (+00:00) and Oracle has the definitions on when this DST change happens stored, so it can adjust it at the right date and time.

The named timezone UTC for example is always +00:00.

Database Timezone (dbtimezone)

Below excerpts from MOS Article 340512.1:

The database time zone is not as important as it sounds. First of all it does not influence functions like SYSDATE, or SYSTIMESTAMP. These function take their contents (date and time, and in the case of SYSTIMESTAMP also time zone) completely from the OS without any "Oracle" intervention.
The only function of the database time zone is that it functions as a time zone in which the values of the "TIMESTAMP WITH LOCAL TIME ZONE" (TSLTZ) datatype are normalized to the current database timezone when they are stored in the database. However, these stored values are always converted into the session time zone on insert and retrieval, so the actual setting of the database time zone is more or less immaterial. The dbtimezone should be set to an offset (+00:00 , -05:00 or +09:00 for example) or a static time zone that is not affected by DST (like UTC or GMT ).
A common misconception is that the database timezone needs to be "your" timezone. This is NOT true. The database timezone has NO relation with "where" the server is located.
There is NO advantage whatsoever in using your timezone or a named timezone as database timezone.
The best setting for dbtimezone is simply +00:00 (or any other OFFSET like -09:00, +08:00, ...), if your current dbtimezone value is an OFFSET then please leave it like it is. The database time zone is only used as a time zone in which stored TSLTZ values are normalized.
So the value of the dbtimezone should in fact not change. Because this is the only task for the database time zone it should not be used for any other things.

The database time zone is usually only set at creation time of the database:
SQL> CREATE DATABASE...
     SET TIME_ZONE='+00:00';
This will only work if there are no TSLTZ values already stored in the database or an ORA-02231 (9i) or ORA-30079 will be seen 

SYSTIMESTAMP

You could say that SYSTIMESTAMP is "SYSDATE with time zone information added".
SYSTIMESTAMP, just like SYSDATE depends on Unix platforms on the UNIX time configuration (= Unix TZ variable) for the Unix session when the database and listener where started.
The precision is platform dependant, on most Unix platforms it's microseconds (10-6) on Windows this is Milliseconds (10-3). The output is defined by NLS_TIMESTAMP_TZ_FORMAT in NLS_SESSION_PARAMETERS.

The SYSTIMESTAMP output has an offset from UTC but is not defined to include an actual named timezone. Mapping this offset to a timezone, or reinterpreting the OS TZ setting would be very hard and error prone and so the code sticks to the absolute offset between UTC and the local time.
You can see this by issuing:

SQL> SELECT EXTRACT( timezone_region from systimestamp ) FROM dual;
EXTRACT(TIMEZONE_REGIONFROMSYSTIMESTAMP)
----------------------------------------------------------------
UNKNOWN

if you want to know the time in a particular time zone you can use "AT TIME ZONE".
SQL> SELECT systimestamp AT TIME ZONE 'Canada/Eastern' FROM DUAL;
SYSTIMESTAMPATTIMEZONE'CANADA/EASTERN'
------------------------------------------------------------------
19-NOV-07 09.47.55.099000 CANADA/EASTERN

if you are wanting to see the timestamp in the sessions timezone then you should use CURRENT_TIMESTAMP.

SQL> ALTER SESSION SET NLS_TIMESTAMP_TZ_FORMAT ='YYYY.MM.DD HH24:MI:SS TZR TZD';
Session altered.
SQL> ALTER SESSION SET TIME_ZONE = 'Canada/Eastern';
Session altered.
SQL> SELECT current_timestamp FROM dual;
CURRENT_TIMESTAMP
---------------------------------------------------------------------------
2007.11.19 09:48:18 CANADA/EASTERN EST

Please note that the DBTIMEZONE has NOTHING to do with this, changing DBTIMEZONE will NOT solve SYSDATE or SYSTIMESTAMP returning a wrong time.

Difference between CURRENT_DATE, LOCALTIMESTAMP and CURRENT_TIMESTAMP?

They all depend on the session timezone, which is defined on the CLIENT side, not server side.

CURRENT_DATE returns the current date and time in the session time zone in a value of datatype DATE.

LOCALTIMESTAMP returns the current date and time in the session time zone in a value of datatype TIMESTAMP.

CURRENT_TIMESTAMP returns the current date and time in the session time zone, in a value of datatype TIMESTAMP WITH TIME ZONE.

The sessions NLS_DATE_FORMAT defines the output format of a DATE, NLS_TIMESTAMP_FORMAT defines the output format of a TIMESTAMP, the NLS_TIMESTAMP_TZ_FORMAT defines the output format of a TIMESTAMP WITH TIME ZONE.



How can I check the session time zone?

The SESSIONTIMEZONE sql function returns the value of the current session's time zone:

SQL> SELECT SESSIONTIMEZONE FROM DUAL;
SESSIONTIMEZONE
---------------
+01:00

How can I set the session time zone?

By default the session timezone is set to the OFFSET of the clients (!) operating system timezone value/setting at connection time. The client asks the client Os what the current offset is to UTC and then , during the connection/session creation fase , does an alter session based on this.
The session time zone can be explicitly set to:
  • O/S local time zone
  • Database time zone
  • An absolute offset
  • A named region
This can be done in 2 ways, the first method consists to use one of the following ALTER SESSION SET TIME_ZONE statements:
SQL> ALTER SESSION SET TIME_ZONE = local;
SQL> ALTER SESSION SET TIME_ZONE = dbtimezone;
SQL> ALTER SESSION SET TIME_ZONE = '-05:00';
SQL> ALTER SESSION SET TIME_ZONE = 'Europe/London';
The alternative method is to set the (client) operating system environment variable ORA_SDTZ:
ORA_SDTZ = 'OS_TZ' | 'DB_TZ' | '[+ | -] hh:mm' | 'timezone_region'
$ ORA_SDTZ='OS_TZ'
$ export ORA_SDTZ
$ ORA_SDTZ='-05:00'
$ export ORA_SDTZ
If you do not want to set ORA_SDTZ on all client machines, but still want to be in control over the session time zone settings for all sessions, then consider using a logon trigger to the database, in which you can set the session time zone specifically through ALTER SESSION (as per point a above).
Note that the session timezone defaults to an offset ( like +05:00), even if the unix TZ variable or Windows timezone region is set to a named TZ. If you need the session timezone to be a named timezone then you need to set ORA_SDTZ client (!) environment (or registry on windows) with an Oracle TZ name.

How can I retrieve the time zone offset corresponding to a time zone region?

The TZ_OFFSET() sql function returns the time zone offset displacement to the input time zone region.

SQL> SELECT TZ_OFFSET('US/Pacific') FROM DUAL;

TZ_OFFS
-------
-07:00
The returned offset depends on the date this statement is executed. For example, in the 'US/Pacific' time zone, it may return '-07:00' or '-08:00' whether daylight saving is in effect or not.



Other Resources


To see a listing of valid time zone region names, query the TZNAME column of the V$TIMEZONE_NAMES dynamic performance view.

SELECT SESSIONTIMEZONE FROM DUAL; http://docs.oracle.com/cd/E11882_01/server.112/e26088/functions162.htm#SQLRF51736


ALTER SESSION SET
TIME_ZONE =  '[+ | -] hh:mm' 
             | LOCAL 
             | DBTIMEZONE 
             | 'time_zone_region'
 MOS:
  1. Briefing by Jonathan Lewis, particularly interesting when considering a column type TIMESTAMP WITH LOCAL TIME ZONE  
  2. 340512.1 Timestamps & time zones – Frequently Asked Questions
  3. ALTER SESSION Reference.

Tuesday, January 14, 2014

Protecting SSH Accesss

Problem

In home instead of a typical router I have a PandaBoard with Debian installed. This very flexible solution allows for running fully customized firewall (iptables), web-proxy (squid) with parental-control and blacklists (dansguardian). This box is a front device of my internal network and allows SSH access. I was rather uncomfortable observing logwatch reports which say about continuous break-in attempts into root and other accounts. While it is quite impossible to guess my password, I rarely change it, so it could be somehow hijacked. So I made a few additional obstacles to reach the SSH while keeping it relatively simple to use.

First option is to limit the access to SSH service itself by terms of PAM. Here are requirements. First I edited /etc/pam.d/sshd file and uncommented third line in the excerpt below:

[...]
# Uncomment and edit /etc/security/access.conf if you need to set complex
# access limits that are hard to express in sshd_config.
account  required     pam_access.so
Then I adjusted /etc/security/access.conf:
[...]
+ : root : 10.1.     89.174.214.
+ : root : kedra.org .kedra.org
# User "root" should be denied to get access from all other sources.
- : root : ALL
# jurek accesses from all sources
+ : jurek : ALL
Above looks good enough to limit unauthorized access for root. The local network and known remote locations are granted SSH access to root. Connection as root from other location is impossible.

OneTimePasswords

Google Authenticator is one time passwords generator, which is use to protect my Gmail and AWS accounts. It gives my a sense of security - without my phone which generates one time password, it is very hard to gain the access to the account. Naturally one time password is an additional level of access so it means I have to provide the classic password + the Google Authenticator one.

First step is to install libpam-google-authenticator (apt-get install), then create an access file which allows to skip pam_google_authenticator when connecting from local network (/etc/security/access-local.conf) with the following content:

# only allow from local IP range
+ : ALL : 10.1.0.0/24
+ : ALL : LOCAL
- : ALL : ALL

then adjust /etc/pam.d/sshd:

[...]
# Uncomment and edit /etc/security/access.conf if you need to set complex
# access limits that are hard to express in sshd_config.
account  required     pam_access.so

# skip one-time password if logging in from the local network
auth [success=1 default=ignore] pam_access.so accessfile=/etc/security/access-local.conf
auth required pam_google_authenticator.so

# Standard Un*x authorization.
@include common-account

# Standard Un*x session setup and teardown.
@include common-session
[...]

The last change is to allow for one time passwords authentication in /etc/ssh/sshd_config:


# Change to yes to enable challenge-response passwords (beware issues with
# some PAM modules and threads)
ChallengeResponseAuthentication yes

Restart the SSH daemon /etc/init.d/ssh restart and generate the key by google-authenticator. The command is verbose and intuitive. On my Android phone I use "Google Authenticator" - it supports QR code scanning or I have to retype just generated key from google-authenticator command. The google-authenticator command creates ~/.google_authenticator only-owner-readable file which stores the key. That's should be it - it works. Well not really.


Configuration Extension

Google Authenticator setup in a way as above is a global configuration for all users. It means the given user has to create its own .google_authenticator file (can't be system shared file until you want to have it world readable) or the user won't be able to login. This is not really what I want here. I'd like to have a situation when user (actually me only) has an option to decide by himself if he wants or not to be protected by it. I'd like also an option to have only a single key (.google_authentication file) but I don't like the idea of having it readable for all users.

There are multiple options to archive above goals. The most straightforward is suggested by the google-authenticator man page. It requires to add a following line:
auth [default=1 success=ignore] pam_succeed_if.so quiet user ingroup root
auth required pam_google_authenticator.so

It requires for user to be in group "root" (last argument) before GoogleAuth is required. I'm not PAM guru so in effect it removed the effect of previous line, that with accessfile=/etc/security/access-local.conf. There is probably an option to overcome it somehow but there was no curiosity to follow this path.

apt-get remove libpam-google-authenticator
apt-get install libpam0g-dev libqrencode3
wget https://google-authenticator.googlecode.com/files/libpam-google-authenticator-1.0-source.tar.bz2
You can check if there is a new version here.
tar jvxf libpam-google-authenticator-1.0-source.tar.bz2
cd libpam-google-authenticator-1.0/
make
make install

Now I can log in without one time password for users where .google_authenticator file is not present the home directory. I also can preview one-time-passwords when typing. The sshd_config needs to be adjusted:
auth required pam_google_authenticator.so nullok echo_verification_code
This is something good to know and good to have. However, since I'm the only user of the system, I'd rather have a common .google_authenticator file, root owned, root only readable. For the internal network I'd like to login without one time passwords, but for the external I want to have it as mandatory. So the final solution is:
# Uncomment and edit /etc/security/access.conf if you need to set complex
# access limits that are hard to express in sshd_config.
#account required pam_access.so

# skip one-time password if logging in from the local network
auth [success=1 default=ignore] pam_access.so accessfile=/etc/security/access-local.conf
auth required pam_google_authenticator.so user=root secret=/root/.google_authenticator echo_verification_code

Finally I decided to open the SSH world wide, no exceptions (pam_access.so commented out in /etc/pam.d/sshd).

References

  1. Remi Bergsma's blog
  2.  How to Setup Two-Factor Authentication (Google Authenticator) for SSH Logins

Friday, January 10, 2014

JDBC Connection Failover

FAN

With JDBC thin 11.2 and simplefan.jar (oracle.simplefan package) I was able to perform tests only with ONS client running locally. The program and the test environment has been described at Martin Bach's blog. Ons can be installed with the full version of Oracle 11.2 Windows client (standard install). It requires changes in the ons.config: usesharedinstall=false and nodes=node1:6200,node2:6200,node3:6200. By default usessharedinstall is set to true, which makes the lock file appending the hostname to it. Consequently it renders the example being not able to found it by the standard name. I didn't investigate how to fix it at the code level.

Speaking on JDBC thin it is suprising how little of information I could find in the Internet. The only valuable information from Oracle comes with Oracle Database RAC FAN Events Java 11g Release 2 (11.2) E13993-01 and there is not working example in Oracle Database JDBC Developer's Guide 11g Release 2 (11.2). Not working not only because it is not quite complete, but because it refers to not existing methods: Actually didn't find methods like getServiceMemberStatus, getServiceCompositeEvent and some others within simplefan.jar and the above API documentation. Searching with Google for these methods returns the above (not working) example only. In a similar way, existing function don't handle coming events properly. The "SHUTDOWN" event is an example here.

The code below is original Oracle's example mixed with Martin Bach's code:

package org.kedra.fan1;
import java.util.Properties;
import oracle.simplefan.FanEventListener;
import oracle.simplefan.FanManager;
import oracle.simplefan.FanSubscription;
import oracle.simplefan.LoadAdvisoryEvent;
import oracle.simplefan.NodeDownEvent;
import oracle.simplefan.ServiceDownEvent;
import oracle.simplefan.ServiceDownEvent.ServiceMemberEvent;

public class Test1 {
 Test1() {
  FanManager fm = FanManager.getInstance();

  //Properties fmProps = new Properties();
  //fmProps.setProperty("onsNodes",
  //  "plabb241:6200,plabb230:6200,plabb229:6200");
  // fmProps.setProperty(key, value)
  // fm.configure(fmProps);

  System.setProperty("oracle.ons.oraclehome",
    "c:\\Oracle2\\product\\11.2.0\\client_1");
  System.out.println(System.getProperty("oracle.ons.oraclehome"));

  Properties props = new Properties();
  props.put("serviceName", "AMQS1");

  FanSubscription sub = fm.subscribe(props);
  System.out.println("I'm subscribed!");

  sub.addListener(new FanEventListener() {

   public void handleEvent(ServiceDownEvent event) {
    System.out.println("ServiceDownEvent!");

    try {
     System.out.println(event.getTimestamp());
     System.out.println("getServiceName: "
       + event.getServiceName());
     System.out.println("getDatabaseUniqueName: "
       + event.getDatabaseUniqueName());
     System.out.println("getReason: " + event.getReason());
     System.out.println("getKind: " + event.getKind());

     ServiceMemberEvent me = event.getServiceMemberEvent();
     if (me != null) {
      System.out.println("getServiceMemberEvent");
      System.out.println("\t getInstanceName: "
        + me.getInstanceName());
      System.out.println("\t getNodeName: "
        + me.getNodeName());
      // System.out.println(me.getServiceMemberStatus());
     }
     // ServiceCompositeEvent ce = se.getServiceCompositeEvent();
     // if (ce != null) {
     // System.out.println(ce.getServiceCompositeStatus());
     // }
    } catch (Throwable t) {
     // handle all exceptions and errors
     System.err.println("handleEvent - ServiceDownEvent");
     t.printStackTrace(System.err);
    }
   }

   public void handleEvent(NodeDownEvent event) {
    System.out.println("Node Down Event!");

    try {
     System.out.println(event.getTimestamp());
     System.out.println("getNodeName: " + event.getNodeName());
     // ServiceCompositeEvent ce = se.getServiceCompositeEvent();
     // if (ce != null) {
     // System.out.println(ce.getServiceCompositeStatus());
     // }
    } catch (Throwable t) {
     System.err.println("handleEvent - ServiceDownEvent");
     t.printStackTrace(System.err);
    }
   }

   public void handleEvent(LoadAdvisoryEvent arg0) {
    System.out.println("Load Advisory event");

    System.out.println("originating database: "
      + arg0.getDatabaseUniqueName());
    System.out.println("originating instance: "
      + arg0.getInstanceName());
    System.out.println("Service Quality     : "
      + arg0.getServiceQuality());
    System.out.println("Percent             : " + arg0.getPercent());
    System.out.println("Service Name        : "
      + arg0.getServiceName());
    System.out.println("Service Quality     : "
      + arg0.getServiceQuality());
    System.out.println("Observed at         : "
      + arg0.getTimestamp() + "\n\n");
   }
  });
 }

 public static void main(String[] args) {
  Test1 tc = new Test1();

  int i = 0;
  while (i < 100000) {
   try {
    Thread.sleep(100);
    i++;
   } catch (Exception e) {
    System.out.println(e);
   }
  }

  System.out.println("execution ended");
 }
}

I would like to see a support for a remote ONS. There is a method configure() in the FanManager class which takes a list of ONS servers but requires mandatory oracle wallet and password as well. This is not something I expect - for I don't want the communication with ONS server over SSL.

Oracle admits it is "the initial release" so the functionality of this library is fairly limited.

Fast Connection Failover

Fast Connection Failover (FCF) and for JDBC thin it us usable with Universal Connection Pool (UCP). There is an option to use JDBC Implicit Connection Cache (ICC) but Oracle considers the feature to be replaced by UCP.

  1. Automatic Workload Management with Oracle Real Application Clusters 11g Release 2 - FAN, FCF
  2. Maximum Availability Architecture, Oracle Best Practices For High Availability: Client Failover Best Practices for Highly Available Oracle  Databases: Oracle Database 11g Release 2 - Standby database oriented.
  3. Fast Connection Failover Example JDBC Thin - this is about 10g High Availability and JDBC. Requires ons.jar or ONS working on the client side. Great resource for hands-on experience.
  4. How to Verify Universal Connection Pool (UCP) / Fast Connection Failover (FCF) Setup (Metalink Doc ID 1064652.1)
  5. JDBC and Universal Connection Pool
  6. UCP Demos Page (Oracle)
  7. TAF vs FAN, FCF vs ONS
  8.  Metalink Resources: