This is an old revision of the document!
Overview
Application Continuity is a new feature and enhancement of the TAF and FCF. Application continuity is composed by two components:
- Transactional Guard
- Transactional Replay
In a nutshell, you will no more wonder if you have to redo your changes if a session is killed or the instance is terminated. Up to now, all your session data (including your transactional data) was wiped, once the instance is destroyed. However from Oracle Database 12c, you can configure a service to record your changes and replay them next time you connect as follows:
Service Creation
Create service actest
[oracle@enode01 labs]$ srvctl add service -db eastdb \ -service actest \ -preferred eastdb1 \ -available eastdb2 \ -clbgoal SHORT \ -rlbgoal SERVICE_TIME \ -failovertype TRANSACTION \ -commit_outcome TRUE \ -failoverretry 30 \ -failoverdelay 5 \ -retention 86400 \ -replay_init_time 1800 \
Startup
[oracle@lparaca ~]$ srvctl status service -serverpool orclsp Service actest of database orcl is not running. [oracle@lparaca ~]$ srvctl start service -db orcl -service actest
Check & Test
[oracle@lparaca ~]$ srvctl status service -serverpool orclsp Service actest of database orcl is running on nodes: lparaca. [oracle@lparaca ~]$ lsnrctl status LSNRCTL for Linux: Version 12.1.0.2.0 - Production on 19-JAN-2018 05:16:01 Copyright (c) 1991, 2014, Oracle. All rights reserved. Connecting to (ADDRESS=(PROTOCOL=tcp)(HOST=)(PORT=1521)) STATUS of the LISTENER ------------------------ Alias LISTENER Version TNSLSNR for Linux: Version 12.1.0.2.0 - Production Start Date 19-JAN-2018 04:02:17 Uptime 0 days 1 hr. 13 min. 44 sec Trace Level off Security ON: Local OS Authentication SNMP OFF Listener Parameter File /u01/app/oracle/grid/network/admin/listener.ora Listener Log File /u01/app/oracle/product/diag/tnslsnr/lparaca/listener/alert/log.xml Listening Endpoints Summary... (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=LISTENER))) (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=192.168.100.50)(PORT=1521))) (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=192.168.100.51)(PORT=1521))) Services Summary... Service "+ASM" has 1 instance(s). Instance "+ASM1", status READY, has 1 handler(s) for this service... Service "actest" has 1 instance(s). <--- **Our new SERVICE** Instance "orcl_1", status READY, has 1 handler(s) for this service... Service "orcl" has 1 instance(s). Instance "orcl_1", status READY, has 1 handler(s) for this service... Service "orclXDB" has 1 instance(s). Instance "orcl_1", status READY, has 1 handler(s) for this service... The command completed successfullyNow your service will failover to the other instance and the uncommited changes will be replayed. Therefore, any node failure will be transparent to the end user.
Application Changes
The application should be changed also be using the UPC = Universal Connection Pooling
Below you can see the source which I have used:
package act; import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; import oracle.ucp.jdbc.PoolDataSourceFactory; import oracle.ucp.jdbc.PoolDataSource; import oracle.ucp.jdbc.ValidConnection; import java.sql.ResultSet; /** * * @author Julien */ public class Actest { /** * @param args the command line arguments */ public static void main(String[] args) throws SQLException, Exception { String message; if (args.length == 0) { message = "default"; } else { message = args[0]; } PoolDataSource pds = PoolDataSourceFactory.getPoolDataSource(); pds.setConnectionFactoryClassName("oracle.jdbc.replay.OracleDataSourceImpl"); System.out.println("connection factory set"); String URL = "jdbc:oracle:thin:@(DESCRIPTION = (TRANSPORT_CONNECT_TIMEOUT=3) (RETRY_COUNT=20)(FAILOVER=ON) " + "(ADDRESS = (PROTOCOL = TCP)(HOST = lparac-scan.myrac.com)(PORT = 1521)) (CONNECT_DATA = " + "(SERVER = DEDICATED) (SERVICE_NAME = ACTEST)))"; System.out.println("Using URL\n" + URL); pds.setURL(URL); pds.setUser("acuser"); pds.setPassword("acpassword"); pds.setInitialPoolSize(10); pds.setMinPoolSize(10); pds.setMaxPoolSize(20); // RAC Features pds.setConnectionPoolName("Application Continuity Pool"); pds.setFastConnectionFailoverEnabled(true); // use srvctl config nodeapps to get the ONS ports on the cluster pds.setONSConfiguration("nodes=192.168.100.50:6200,192.168.100.60:6200"); System.out.println("pool configured, trying to get a connection"); Connection conn = pds.getConnection(); if (conn == null || !((ValidConnection) conn).isValid()) { System.out.println("connection is not valid"); throw new Exception ("invalid connection obtained from the pool"); } if ( conn instanceof oracle.jdbc.replay.ReplayableConnection ) { System.out.println("got a replay data source"); } else { System.out.println("this is not a replay data source. Why not?"); } System.out.println("got a connection! Getting some stats if possible"); oracle.ucp.jdbc.JDBCConnectionPoolStatistics stats = pds.getStatistics(); System.out.println("\tgetAvailableConnectionsCount() " + stats.getAvailableConnectionsCount()); System.out.println("\tgetBorrowedConnectionsCount() " + stats.getBorrowedConnectionsCount() ); System.out.println("\tgetRemainingPoolCapacityCount() " + stats.getRemainingPoolCapacityCount()); System.out.println("\tgetTotalConnectionsCount() " + stats.getTotalConnectionsCount()); System.out.println(((oracle.ucp.jdbc.oracle.OracleJDBCConnectionPoolStatistics)pds.getStatistics()).getFCFProcessingInfo()); System.out.println("Now working"); java.sql.CallableStatement cstmt = conn.prepareCall("{call callProc(?)}"); cstmt.setString(1, message); cstmt.execute(); System.out.println("Statement executed. Now closing down"); System.out.println("Almost done! Getting some more stats if possible"); stats = pds.getStatistics(); System.out.println("\tgetAvailableConnectionsCount() " + stats.getAvailableConnectionsCount()); System.out.println("\tgetBorrowedConnectionsCount() " + stats.getBorrowedConnectionsCount() ); System.out.println("\tgetRemainingPoolCapacityCount() " + stats.getRemainingPoolCapacityCount()); System.out.println("\tgetTotalConnectionsCount() " + stats.getTotalConnectionsCount()); System.out.println(((oracle.ucp.jdbc.oracle.OracleJDBCConnectionPoolStatistics)pds.getStatistics()).getFCFProcessingInfo()); cstmt.close(); conn.close(); conn = null; } }
Once the code is compiled can be run via:
C:\Users\Julien>java -jar -Djava.util.logging.config.file=logging.properties.txt C:\Users\Julien\Documents\NetBeansProjects\actest\dist\actest.jar all_out_loggi ng2 connection factory set Using URL jdbc:oracle:thin:@(DESCRIPTION = (TRANSPORT_CONNECT_TIMEOUT=3) (RETRY_COUNT=20)( FAILOVER=ON) (ADDRESS = (PROTOCOL = TCP)(HOST = lparac-scan.myrac.com)(PORT = 15 21)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = ACTEST))) pool configured, trying to get a connection C:\Users\Julien>