Failover in High Availability Systems

A high availability cluster includes two or more machines that are configured so that if one machine (or application) is interrupted, the second machine assumes the workload of both machines.

Each of these machines is called one node of the high availability cluster. A high availability cluster is used in an environment that must always be available, such as a banking system to which clients must connect continuously, 365 days a year.

The machines are configured so that each machine can read the other machine's disks, although not at the same time. (All of the disks that are failed-over should be shared disks).

High Availability Cluster Using Failover
*

For example, if Adaptive Server 1 is the primary companion server, and it fails, Adaptive Server 2, as the secondary companion server, reads its disks (disks 1 – 4) and manages any databases on them until Adaptive Server 1 can be restarted. Any clients connected to Adaptive Server 1 are automatically connected to Adaptive Server 2.

Failover allows Adaptive Server to work in a high availability cluster in active-active or active-passive configuration.

During failover, clients connected to the primary companion using the failover property automatically reestablish their network connections to the secondary companion. Failover can be enabled by setting the connection property HASession to 1 (default value is “0”). If this property is not set, the session failover does not occur, even if the server is configured for failover. You must also set SecondaryServer (the IP address or the machine name of the secondary Adaptive Server) and SecondaryPort (the port number of the secondary Adaptive Server) properties. See Adaptive Server Enterprise Using Sybase Failover in a High Availability System for information about configuring your system for high availability.

When the Adaptive Server ODBC Driver detects a connection failure with the primary Adaptive Server, it first tries to reconnect to the primary. If it cannot reconnect, it assumes that a failover has occurred. Then, it automatically tries to connect to the secondary Adaptive Server using the connection properties set in SecondaryServer, and SecondaryPort.

Successful Failover Confirmation

If a connection to the secondary server is established, the Adaptive Server ODBC Driver returns SQL_ERROR for the function return code. To confirm a successful failover, examine the SQLState and NativeError messages for values of 08S01 and 30130 respectively. The error message returned on such failover is:
“Connection to Sybase server has been lost, you have been successfully connected to the next available HA server. All active transactions have been rolled back.”
You can access these values by calling SQLGetDiagRec on the StatementHandle. Then, the client must reapply the failed transaction with the new connection. If failover occurs while a transaction is open, only changes that were committed to the database before failover are retained.

An Unsuccessful Failover Verification

If the connection to the secondary server is not established, the Adaptive Server ODBC Driver returns SQL_ERROR for the function return code.

To confirm that failover did not occur, examine the SQLState and NativeError for values of 08S01 and 30131. The error message returned on an unsuccessful failover is:
“Connection to Sybase server has been lost, connection to the next available HA server also failed. All active transactions have been rolled back”.
You can access these values by calling SQLGetDiagRec on the StatementHandle.

To code for a failover:

/* Declare required variables */
....
/* Open Database connection */
....
/* Perform a transaction */
...
/* Check return code and handle failover */
if( retcode == SQL_ERROR )
{
   retcode = SQLGetDiagRec(stmt, 1,
      sqlstate,&NativeError, errmsg,100, NULL );
   if(retcode == SQL_SUCCESS || 
      retcode == SQL_SUCCESS_WITH_INFO)
   {
        if(NativeError == 30130 )
        {
        /* Successful failover retry transaction*/
        ...
        }
     else if (NativeError == 30131)
     {
        /* Failover failed. Return error */
        ...
     }
   }	
}