🖥️ Environment Details :🗄️Database Version: Oracle Database 26ai (23.26.1.0.0) 🐧Operating System: Oracle Enterprise Linux (OEL) 8.10 🧪Test Environment: All observations and performance metrics presented in this document were collected and validated on the above environment configuration. 📌 Disclaimer: The observations, behavior, and metrics presented in this blog post are based on Transparent Application Continuity (TAC) testing performed in my current Oracle Database environment and configuration. Actual TAC behavior, failover or replay results, and performance may vary depending on factors such as the Oracle Database version, JDBC client version, application architecture, connection pool configuration, service configuration, network environment, workload, and transaction patterns. Therefore, thorough testing with the actual application workload and configuration is strongly recommended before implementing TAC in a production environment. 📚 Quick Steps : 🎯 Requirement / Need for TAC (Transparent Application Continuity) 💡 What is TAC (Transparent Application Continuity)? ✅ TAC (Transparent Application Continuity) Client Compatibility ⚙️ Important TAC Parameters 🔵 Step-by-Step Configuration of TAC Using SCAN 🔐 Step-by-Step Configuration of TAC Using VIP 🌐 Step-by-Step Configuration of TAC Using Public Hostnames 🔗 JDBC Connection Strings for Application Configuration ⚠️ Important Note: Application-Level TAC Testing |
|
Let's first understand the requirement or need for TAC (Transparent Application Continuity): Applications are continuously connected to the database to process user requests. Sometimes, database connections can be interrupted due to following reasons: - Planned Maintenance Activities – Patching, Upgrades, Database Maintenance. - Unplanned Failures – DB Instance Failure, Server Failure, Storage or Infrastructure Failure, Network issues. - RAC Instance Activities – An application Connections may need to move from one RAC DB instance to another instance. In simple words, suppose, a user clicks on submit button to process his request, and at that exact point of time, the database instance serving the application goes down. As a result, the user's request is interrupted and may fail. This is the problem that TAC is designed to handle. |
|
What is TAC (Transparent Application Continuity) ? Transparent Application Continuity (TAC) an Oracle feature that helps applications keep running when there is planned maintenance or an unexpected database failure. |
|
1) SQL*Plus - version 19c and above 2) Oracle WebLogic Server - version 18c and above 3) UCP(Oracle Universal Connection Pool) - version 18c and above 4) OCI Session Pool and OCI-based applications - version 19c and above 5) Java applications and connection pools - Oracle JDBC Replay Driver 12c or newer 6) ODP.NET Unmanaged Provider - version 18c and above 7) Oracle JDBC Replay Driver - version 18c and above |
1) FAILOVER_TYPE : AUTO | TRANSACTION | NONE This tells Oracle which failover/replay mechanism should be used when the database connection is interrupted. AUTO: Oracle automatically determines which session states need to be restored and replays eligible database requests after a failure. TRANSACTION: When a database instance fails, this handles the outage transparently by automatically restoring the session and replaying eligible in-flight transactions on an available database instance. NONE: Application Continuity replay is disabled. 2) FAILOVER_RESTORE : AUTO | LEVEL1 This defines how the database session state is restored after a failover. AUTO: It automatically restores the session state needed for Application Continuity/TAC when the connection moves to another available database instance. 3) COMMIT_OUTCOME : TRUE | FALSE This option determines whether the transaction commit outcome is accessible after the COMMIT has executed and an outage has occurred. TRUE : Transaction Guard makes the commit outcome accessible after an outage. FALSE : Commit outcome is not made accessible through the service. 4) RETENTION : This specifies how long (in seconds) Transaction Guard retains the commit outcome. 5) DRAIN_TIMEOUT : Time (in seconds) allowed for sessions to drain during planned maintenance. 6) STOP_OPTION : IMMEDIATE | TRANSACTIONAL This controls how the service is stopped or drained. IMMEDIATE : Stops the service immediately. Existing sessions are disconnected without waiting for transactions to finish. TRANSACTIONAL : Allows active transactions to complete before sessions are disconnected. 7) RESET_STATE : LEVEL1 This controls session state cleanup or reset operation when connections return to the pool. LEVEL1 : This enables automatic resetting of session states at the end of request. 8) REPLAY_INITIATION_TIMEOUT : This specifies the maximum time (in seconds) allowed to start replay after a request starts if a database outage or failover occurs. 9) FAILOVER_DELAY : This specifies the delay (in seconds) between each connection retry attempt after a database outage or failover occurs. This means Oracle will wait till that time between each retry attempt to reconnect to an available database instance. 10) FAILOVER_RETRIES : This specifies the number of times the Oracle client attempts to reconnect to the database after an outage or failover occurs. |
Step by step configuration of TAC using SCAN Step 1: Lets capture the below CRS details before starting TAC configuration. [oracle@dbnode1 admin]$ cat /etc/hosts 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 #Public IP 10.20.30.101 dbnode1.localdomain dbnode1 10.20.30.102 dbnode2.localdomain dbnode2 #Private IP 10.1.2.201 dbnode1-priv.localdomain dbnode1-priv 10.1.2.202 dbnode2-priv.localdomain dbnode2-priv #VIP IP 10.20.30.103 dbnode1-vip.localdomain dbnode1-vip 10.20.30.104 dbnode2-vip.localdomain dbnode2-vip #scan IP 10.20.30.105 dbnode-scan.localdomain dbnode-scan [oracle@dbnode1 ~]$ id uid=1002(oracle) gid=2000(oinstall) groups=2000(oinstall),2100(asmadmin),2200(dba),2300(oper),2400(asmdba),2500(asmoper) [oracle@dbnode1 ~]$ . oraenv ORACLE_SID = [oracle] ? PR1 The Oracle base has been set to /u01/app/oracle [oracle@dbnode1 ~]$ env | grep ORA ORACLE_SID=PR1 ORACLE_BASE=/u01/app/oracle ORACLE_HOME=/u01/app/oracle/product/23.0.0/dbhome_1 [oracle@dbnode1 ~]$ ps -ef | grep pmon grid 9625 1 0 22:43 ? 00:00:00 asm_pmon_+ASM1 oracle 13214 1 1 22:44 ? 00:00:00 ora_pmon_PR1 [oracle@dbnode1 ~]$ srvctl status db -d PR Instance PR1 is running on node dbnode1 Instance PR2 is running on node dbnode2 [oracle@dbnode1 ~]$ srvctl config scan SCAN name: dbnode-scan, Network: 1 Subnet IPv4: 10.20.30.0/255.255.255.0/enp0s3, static Subnet IPv6: SCAN 1 IPv4 VIP: 10.20.30.105 SCAN VIP is enabled. [oracle@dbnode1 ~]$ srvctl config scan_listener SCAN Listeners for network 1: Registration invited nodes: Registration invited subnets: Endpoints: TCP:1530 SCAN Listener LISTENER_SCAN1 exists SCAN Listener is enabled. Step 2: Lets create and start TAC service and verify it's configuration. [oracle@dbnode1 ~]$ srvctl add service -db PR -service TAC_SERVICE -preferred PR1,PR2 -failovertype AUTO -failover_restore AUTO -failoverdelay 5 -failoverretry 30 -commit_outcome TRUE -replay_init_time 600 [oracle@dbnode1 ~]$ srvctl config service -db PR -service TAC_SERVICE Service name: TAC_SERVICE Cardinality: 2 Service role: PRIMARY Management policy: AUTOMATIC DTP transaction: FALSE AQ HA notifications: FALSE Global: FALSE Commit Outcome: TRUE Commit Outcome Fastpath: TRUE Reset State: NONE Failover type: AUTO Failover method: BASIC Failover retries: 30 Failover delay: 5 Failover restore: AUTO Connection Load Balancing Goal: LONG Runtime Load Balancing Goal: NONE TAF policy specification: NONE Edition: Pluggable database name: True Cache service: Maximum lag time: ANY SQL Translation Profile: Retention: 86400 seconds Failback : no Replay Initiation Time: 600 seconds Drain timeout: Template timeout: 86400 seconds Stop option: Session State Consistency: AUTO Auto Connection Rebalance: DEFAULT GSM Flags: 0 Service is enabled Preferred instances: PR1,PR2 Available instances: CSS critical: no [oracle@dbnode1 ~]$ srvctl start service -db PR -service TAC_SERVICE [oracle@dbnode1 ~]$ srvctl status service -db PR -service TAC_SERVICE Service TAC_SERVICE is running on instances PR1,PR2 Step 3: Add tns entry for newly created TAC service on all cluster nodes. [oracle@dbnode1 ~]$ cat /u01/app/oracle/product/23.0.0/dbhome_1/network/admin/tnsnames.ora TAC_SCAN = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = dbnode-scan)(PORT = 1530)) (CONNECT_DATA = (SERVICE_NAME = tac_service.localdomain) ) ) [oracle@dbnode2 ~]$ cat /u01/app/oracle/product/23.0.0/dbhome_1/network/admin/tnsnames.ora TAC_SCAN = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = dbnode-scan)(PORT = 1530)) (CONNECT_DATA = (SERVICE_NAME = tac_service.localdomain) ) ) Step 4: Login as grid user and check the LISTENER_SCAN1 status. [oracle@dbnode1 admin]$ ps -ef | grep tns grid 12301 1 0 22:44 ? 00:00:00 /u01/app/23.0.0/grid/bin/tnslsnr ASMNET1LSNR_ASM -no_crs_notify -inherit grid 12448 1 0 22:44 ? 00:00:00 /u01/app/23.0.0/grid/bin/tnslsnr LISTENER -no_crs_notify -inherit grid 12516 1 0 22:44 ? 00:00:00 /u01/app/23.0.0/grid/bin/tnslsnr LISTENER_SCAN1 -no_crs_notify -inherit [oracle@dbnode1 ~]$ su - grid Password: [grid@dbnode1 ~]$ . oraenv ORACLE_SID = [grid] ? +ASM1 The Oracle base has been set to /u01/app/grid [grid@dbnode1 ~]$ lsnrctl status LISTENER_SCAN1 LSNRCTL for Linux: Version 23.26.1.0.0 - Production on 22-AUG-2026 22:59:57 Copyright (c) 1991, 2026, Oracle. All rights reserved. Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=LISTENER_SCAN1))) STATUS of the LISTENER ------------------------ Alias LISTENER_SCAN1 Version TNSLSNR for Linux: Version 23.26.1.0.0 - Production Start Date 22-AUG-2026 22:44:28 Uptime 0 days 0 hr. 15 min. 28 sec Trace Level off Security ON: Local OS Authentication SNMP OFF Listener Parameter File /u01/app/23.0.0/grid/network/admin/listener.ora Listener Log File /u01/app/grid/diag/tnslsnr/dbnode1/listener_scan1/alert/log.xml Listening Endpoints Summary... (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=LISTENER_SCAN1))) (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=10.20.30.105)(PORT=1530))) Services Summary... Service "4b15f67858842252e063661e140a2ab1.localdomain" has 2 instance(s). Instance "PR1", status READY, has 1 handler(s) for this service... Instance "PR2", status READY, has 1 handler(s) for this service... Service "PR.localdomain" has 2 instance(s). Instance "PR1", status READY, has 1 handler(s) for this service... Instance "PR2", status READY, has 1 handler(s) for this service... Service "PRXDB.localdomain" has 2 instance(s). Instance "PR1", status READY, has 1 handler(s) for this service... Instance "PR2", status READY, has 1 handler(s) for this service... Service "prpdb1.localdomain" has 2 instance(s). Instance "PR1", status READY, has 1 handler(s) for this service... Instance "PR2", status READY, has 1 handler(s) for this service... Service "tac_service.localdomain" has 2 instance(s). Instance "PR1", status READY, has 1 handler(s) for this service... Instance "PR2", status READY, has 1 handler(s) for this service... The command completed successfully Here, in my testing environment, I have configured only one SCAN listener; hence, there is no need to check the status of SCAN listeners on another node. If multiple SCAN listeners are configured in your environment, you can verify the status of the other SCAN listeners accordingly. Step 5: Let's simulate the TAC testing with examples. #Create dummy tablespace and user along with grants. Since this is a pluggable database (PDB) environment, we will create a common user in the container database (CDB) for testing purposes. [oracle@dbnode1 ~]$ sqlplus / as sysdba SQL*Plus: Release 23.26.1.0.0 - Production on Sat Aug 22 23:01:21 2026 Version 23.26.1.0.0 Copyright (c) 1982, 2025, Oracle. All rights reserved. Connected to: Oracle AI Database 26ai Enterprise Edition Release 23.26.1.0.0 - Production Version 23.26.1.0.0 SQL> select name,open_mode from gv$database; NAME OPEN_MODE --------- -------------------- PR READ WRITE PR READ WRITE SQL> create user C##TEST identified by test123; User created. SQL> grant create session,connect to C##TEST; Grant succeeded. SQL> create tablespace TBS_TEST datafile '+DG_DATA' size 500m; Tablespace created. SQL> alter user C##TEST default tablespace TBS_TEST; User altered. SQL> alter user C##TEST quota unlimited on TBS_TEST; User altered. SQL> grant create table to C##TEST; Grant succeeded. SQL> grant select_catalog_role to C##TEST; Grant succeeded. #Connect the created user using TNS alias TAC_SCAN. [oracle@dbnode1 ~]$ sqlplus C##TEST/test123@TAC_SCAN SQL*Plus: Release 23.26.1.0.0 - Production on Sat Aug 22 23:17:24 2026 Version 23.26.1.0.0 Copyright (c) 1982, 2025, Oracle. All rights reserved. Last Successful login time: Sat Aug 22 2026 23:16:47 +05:30 Connected to: Oracle AI Database 26ai Enterprise Edition Release 23.26.1.0.0 - Production Version 23.26.1.0.0 SQL> set time on 23:16:46 SQL> create table demo(id number(5), name varchar2(20)); Table created. 23:17:34 SQL> select failover_type, failover_method, failed_over from v$session where sid=sys_context('userenv', 'sid'); FAILOVER_TYPE FAILOVER_M FAI ------------- ---------- --- AUTO BASIC NO 23:17:40 SQL> col HOST_NAME for a45 23:17:45 SQL> select host_name,instance_name from v$instance; HOST_NAME INSTANCE_NAME -------------------- ---------------- dbnode1.localdomain PR1 23:17:49 SQL> insert into demo values(1,'Apple'); 1 row created. 23:17:56 SQL> insert into demo values(2,'Mango'); 1 row created. 23:18:01 SQL> .......... ........... ........... Please note that I have not executed a COMMIT here. Now, let’s abort or stop this instance from another session and observe how TAC handles the transaction and session recovery. Do not close the above session....let's wait.... From another session, source the environment and stop the DB node instance 1. [oracle@dbnode1 ~]$ . oraenv ORACLE_SID = [oracle] ? PR1 The Oracle base has been set to /u01/app/oracle [oracle@dbnode1 ~]$ env | grep ORA ORACLE_SID=PR1 ORACLE_BASE=/u01/app/oracle ORACLE_HOME=/u01/app/oracle/product/23.0.0/dbhome_1 [oracle@dbnode1 ~]$ date Sat Aug 22 23:18:29 IST 2026 [oracle@dbnode1 ~]$ srvctl stop instance -d PR -i PR1 -force [oracle@dbnode1 ~]$ [oracle@dbnode1 ~]$ srvctl status db -d PR Instance PR1 is not running on node dbnode1 Instance PR2 is running on node dbnode2 Node1 DB Alert Log: 2026-08-22T23:21:54.798533+05:30 Stopped service TAC_SERVICE Shutting down ORACLE instance (immediate) (OS id: 16252) Shutdown is initiated by oraagent.bin@dbnode1.localdomain (TNS V1-V3). Stopping background process SMCO. Shutting down instance: further logons disabled 2026-08-22T23:21:55.060227+05:30 Stopping background process CJQ0 Stopping background process MMNL. 2026-08-22T23:21:55.197220+05:30 Process termination requested for pid 15943 (Q002) [source = rdbms], [info = 2] [request issued by pid: 15938, uid: 1002] Stopping background process MMON. alter pluggable database all close immediate Completed: alter pluggable database all close immediate 2026-08-22T23:21:55.448957+05:30 PDB$SEED(2):JIT: pid 16252 requesting stop License high water mark = 12 Data Pump shutdown in progress 2026-08-22T23:21:55.711941+05:30 Process termination requested for pid 46247 (oraclePR1) [source = rdbms], [info = 2] [request issued by pid: 16252, uid: 1002] 2026-08-22T23:21:55.713126+05:30 Process termination requested for pid 23488 (PPA7) [source = rdbms], [info = 2] [request issued by pid: 16252, uid: 1002] 2026-08-22T23:21:55.717486+05:30 Process termination requested for pid 48486 (PPA6) [source = rdbms], [info = 2] [request issued by pid: 16252, uid: 1002] 2026-08-22T23:21:55.718584+05:30 Process termination requested for pid 15907 (P003) [source = rdbms], [info = 2] [request issued by pid: 16252, uid: 1002] 2026-08-22T23:21:55.721338+05:30 Process termination requested for pid 14903 (P000) [source = rdbms], [info = 2] [request issued by pid: 16252, uid: 1002] 2026-08-22T23:21:56.745688+05:30 ALTER DATABASE CLOSE NORMAL /* db agent *//* {0:0:0} */ alter pluggable database all close immediate Completed: alter pluggable database all close immediate alter pluggable database all close immediate Completed: alter pluggable database all close immediate 2026-08-22T23:21:57.126079+05:30 IM on ADG: Start of Empty Journal IM on ADG: End of Empty Journal Stopping change tracking 2026-08-22T23:21:57.565000+05:30 Redo thread 1 internally disabled at seq 31 (LGWR) 2026-08-22T23:21:57.796333+05:30 ARC3 (PID:15122): Archiving disabled T-1.S-31 [krse.c:7451] 2026-08-22T23:21:57.911436+05:30 ARC3 (PID:15122): Archived Log entry 63 added for B-1225547593.T-1.S-31 LOS:0x000000000177207c NXS:0x00000000017747f6 NAB:24658 ID 0xae0d24c6 LAD:1 [krse.c:4883] 2026-08-22T23:21:58.720237+05:30 Thread 1 closed at log sequence 31 Successful close of redo thread 1 2026-08-22T23:21:58.818193+05:30 Entire Buffer Cache invalidation started Entire Buffer Cache invalidation completed Completed: ALTER DATABASE CLOSE NORMAL /* db agent *//* {0:0:0} */ ALTER DATABASE DISMOUNT /* db agent *//* {0:0:0} */ Completed: ALTER DATABASE DISMOUNT /* db agent *//* {0:0:0} */ 2026-08-22T23:21:59.647533+05:30 JIT: pid 16252 requesting stop 2026-08-22T23:21:59.949427+05:30 JIT: pid 16252 requesting stop SHUTDOWN: waiting for detached processes 'CLMN' to terminate. 2026-08-22T23:22:01.019762+05:30 NOTE: Could not deregister group num 1.197148470 2026-08-22T23:22:01.019863+05:30 NOTE: Could not deregister group num 2.198197047 2026-08-22T23:22:01.019918+05:30 NOTE: Could not deregister group num 5.200294202 2026-08-22T23:22:01.019957+05:30 NOTE: Could not deregister group num 4.199245625 Stopping background process RBAL. NOTE: ASMB exiting 2026-08-22T23:22:02.095394+05:30 freeing the pdb enqueue rht Instance shutdown complete (OS id: 16252) Let's verify the LISTENER_SCAN1 status.... [oracle@dbnode1 ~]$ ps -ef | grep tns grid 12301 1 0 22:44 ? 00:00:00 /u01/app/23.0.0/grid/bin/tnslsnr ASMNET1LSNR_ASM -no_crs_notify -inherit grid 12448 1 0 22:44 ? 00:00:00 /u01/app/23.0.0/grid/bin/tnslsnr LISTENER -no_crs_notify -inherit grid 12516 1 0 22:44 ? 00:00:00 /u01/app/23.0.0/grid/bin/tnslsnr LISTENER_SCAN1 -no_crs_notify -inherit [oracle@dbnode1 ~]$ su - grid Password: [grid@dbnode1 ~]$ . oraenv ORACLE_SID = [grid] ? +ASM1 The Oracle base has been set to /u01/app/grid [grid@dbnode1 ~]$ lsnrctl status LISTENER_SCAN1 LSNRCTL for Linux: Version 23.26.1.0.0 - Production on 22-AUG-2026 23:24:11 Copyright (c) 1991, 2026, Oracle. All rights reserved. Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=LISTENER_SCAN1))) STATUS of the LISTENER ------------------------ Alias LISTENER_SCAN1 Version TNSLSNR for Linux: Version 23.26.1.0.0 - Production Start Date 22-AUG-2026 22:44:28 Uptime 0 days 0 hr. 39 min. 42 sec Trace Level off Security ON: Local OS Authentication SNMP OFF Listener Parameter File /u01/app/23.0.0/grid/network/admin/listener.ora Listener Log File /u01/app/grid/diag/tnslsnr/dbnode1/listener_scan1/alert/log.xml Listening Endpoints Summary... (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=LISTENER_SCAN1))) (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=10.20.30.105)(PORT=1530))) Services Summary... Service "4b15f67858842252e063661e140a2ab1.localdomain" has 1 instance(s). Instance "PR2", status READY, has 1 handler(s) for this service... Service "PR.localdomain" has 1 instance(s). Instance "PR2", status READY, has 1 handler(s) for this service... Service "PRXDB.localdomain" has 1 instance(s). Instance "PR2", status READY, has 1 handler(s) for this service... Service "prpdb1.localdomain" has 1 instance(s). Instance "PR2", status READY, has 1 handler(s) for this service... Service "tac_service.localdomain" has 1 instance(s). Instance "PR2", status READY, has 1 handler(s) for this service... The command completed successfully As we observed in the database alert log, the TAC service on Node 1 is down, while it is still running on Node 2. Now, let’s return to the original session and verify the session recovery using TAC. 23:18:01 SQL> .......... ........... ........... 23:24:38 SQL> 23:24:38 SQL> 23:24:41 SQL> select * from demo; ID NAME ---------- -------------------- 1 Apple 2 Mango 23:24:50 SQL> 23:24:51 SQL> select host_name,instance_name from v$instance; HOST_NAME INSTANCE_NAME --------------------------------------------- ---------------- dbnode2.localdomain PR2 23:24:59 SQL> 23:25:01 SQL> 23:26:18 SQL> commit; Commit complete. 23:26:20 SQL> As you can see, the original session remained active without displaying any errors or interruption to the user. TAC transparently recovered the session and re-established the connection on the surviving node in the background. This occurred even though the transaction had not yet been committed. From the application or user perspective, the failover was seamless, and the user can now execute COMMIT to successfully complete the transaction. |
Step by step configuration of TAC using VIP Step 1: Lets capture the below details before starting TAC configuration. [oracle@dbnode1 admin]$ cat /etc/hosts 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 #Public IP 10.20.30.101 dbnode1.localdomain dbnode1 10.20.30.102 dbnode2.localdomain dbnode2 #Private IP 10.1.2.201 dbnode1-priv.localdomain dbnode1-priv 10.1.2.202 dbnode2-priv.localdomain dbnode2-priv #VIP IP 10.20.30.103 dbnode1-vip.localdomain dbnode1-vip 10.20.30.104 dbnode2-vip.localdomain dbnode2-vip #scan IP 10.20.30.105 dbnode-scan.localdomain dbnode-scan Step 2: Add below VIP tns entry for TAC service on all cluster nodes. [oracle@dbnode1 ~]$ cat /u01/app/oracle/product/23.0.0/dbhome_1/network/admin/tnsnames.ora TAC_VIP = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = dbnode1-vip)(PORT = 1521)) (ADDRESS = (PROTOCOL = TCP)(HOST = dbnode2-vip)(PORT = 1521)) (CONNECT_DATA = (SERVICE_NAME = tac_service.localdomain) ) ) [oracle@dbnode2 ~]$ cat /u01/app/oracle/product/23.0.0/dbhome_1/network/admin/tnsnames.ora TAC_VIP = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = dbnode1-vip)(PORT = 1521)) (ADDRESS = (PROTOCOL = TCP)(HOST = dbnode2-vip)(PORT = 1521)) (CONNECT_DATA = (SERVICE_NAME = tac_service.localdomain) ) ) #Check the local listener status on both nodes. Since we are using VIP addresses in the TNS configuration, verify the status of the local listener on both RAC nodes to ensure that the TAC service is properly registered and running on the appropriate instances. Node1: [grid@dbnode1 ~]$ . oraenv ORACLE_SID = [grid] ? +ASM1 The Oracle base has been set to /u01/app/grid [grid@dbnode1 ~]$ lsnrctl status LSNRCTL for Linux: Version 23.26.1.0.0 - Production on 23-AUG-2026 00:04:39 Copyright (c) 1991, 2026, Oracle. All rights reserved. Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=LISTENER))) STATUS of the LISTENER ------------------------ Alias LISTENER Version TNSLSNR for Linux: Version 23.26.1.0.0 - Production Start Date 23-AUG-2026 00:03:27 Uptime 0 days 0 hr. 1 min. 11 sec Trace Level off Security ON: Local OS Authentication SNMP OFF Listener Parameter File /u01/app/23.0.0/grid/network/admin/listener.ora Listener Log File /u01/app/grid/diag/tnslsnr/dbnode1/listener/alert/log.xml Listening Endpoints Summary... (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=LISTENER))) (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=10.20.30.101)(PORT=1521))) (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=10.20.30.103)(PORT=1521))) Services Summary... Service "+ASM" has 1 instance(s). Instance "+ASM1", status READY, has 1 handler(s) for this service... Service "+ASM_DG_ARCH" has 1 instance(s). Instance "+ASM1", status READY, has 1 handler(s) for this service... Service "+ASM_DG_DATA" has 1 instance(s). Instance "+ASM1", status READY, has 1 handler(s) for this service... Service "+ASM_DG_OCR" has 1 instance(s). Instance "+ASM1", status READY, has 1 handler(s) for this service... Service "+ASM_DG_REDO1" has 1 instance(s). Instance "+ASM1", status READY, has 1 handler(s) for this service... Service "+ASM_DG_REDO2" has 1 instance(s). Instance "+ASM1", status READY, has 1 handler(s) for this service... Service "4b15f67858842252e063661e140a2ab1.localdomain" has 1 instance(s). Instance "PR1", status READY, has 1 handler(s) for this service... Service "PR.localdomain" has 1 instance(s). Instance "PR1", status READY, has 1 handler(s) for this service... Service "PRXDB.localdomain" has 1 instance(s). Instance "PR1", status READY, has 1 handler(s) for this service... Service "prpdb1.localdomain" has 1 instance(s). Instance "PR1", status READY, has 1 handler(s) for this service... Service "tac_service.localdomain" has 1 instance(s). Instance "PR1", status READY, has 1 handler(s) for this service... The command completed successfully Node2: [grid@dbnode2 ~]$ . oraenv ORACLE_SID = [grid] ? +ASM1 The Oracle base has been set to /u01/app/grid [grid@dbnode2 ~]$ lsnrctl status LSNRCTL for Linux: Version 23.26.1.0.0 - Production on 23-AUG-2026 00:09:11 Copyright (c) 1991, 2026, Oracle. All rights reserved. Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=LISTENER))) STATUS of the LISTENER ------------------------ Alias LISTENER Version TNSLSNR for Linux: Version 23.26.1.0.0 - Production Start Date 23-AUG-2026 00:07:25 Uptime 0 days 0 hr. 1 min. 46 sec Trace Level off Security ON: Local OS Authentication SNMP OFF Listener Parameter File /u01/app/23.0.0/grid/network/admin/listener.ora Listener Log File /u01/app/grid/diag/tnslsnr/dbnode2/listener/alert/log.xml Listening Endpoints Summary... (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=LISTENER))) (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=10.20.30.102)(PORT=1521))) (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=10.20.30.104)(PORT=1521))) Services Summary... Service "+ASM" has 1 instance(s). Instance "+ASM2", status READY, has 1 handler(s) for this service... Service "+ASM_DG_ARCH" has 1 instance(s). Instance "+ASM2", status READY, has 1 handler(s) for this service... Service "+ASM_DG_DATA" has 1 instance(s). Instance "+ASM2", status READY, has 1 handler(s) for this service... Service "+ASM_DG_OCR" has 1 instance(s). Instance "+ASM2", status READY, has 1 handler(s) for this service... Service "+ASM_DG_REDO1" has 1 instance(s). Instance "+ASM2", status READY, has 1 handler(s) for this service... Service "+ASM_DG_REDO2" has 1 instance(s). Instance "+ASM2", status READY, has 1 handler(s) for this service... Service "4b15f67858842252e063661e140a2ab1.localdomain" has 1 instance(s). Instance "PR2", status READY, has 1 handler(s) for this service... Service "PR.localdomain" has 1 instance(s). Instance "PR2", status READY, has 1 handler(s) for this service... Service "PRXDB.localdomain" has 1 instance(s). Instance "PR2", status READY, has 1 handler(s) for this service... Service "prpdb1.localdomain" has 1 instance(s). Instance "PR2", status READY, has 1 handler(s) for this service... Service "tac_service.localdomain" has 1 instance(s). Instance "PR2", status READY, has 1 handler(s) for this service... The command completed successfully Step 3: Let's connect to the database by TEST user using tns alias "TAC_VIP". [oracle@dbnode1 ~]$ . oraenv ORACLE_SID = [oracle] ? PR1 The Oracle base has been set to /u01/app/oracle [oracle@dbnode1 admin]$ tnsping TAC_VIP TNS Ping Utility for Linux: Version 23.26.1.0.0 - Production on 23-AUG-2026 00:06:50 Copyright (c) 1997, 2026, Oracle. All rights reserved. Used parameter files: Used TNSNAMES adapter to resolve the alias Attempting to contact (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = dbnode1-vip)(PORT = 1521)) (ADDRESS = (PROTOCOL = TCP)(HOST = dbnode2-vip)(PORT = 1521)) (CONNECT_DATA = (SERVICE_NAME = tac_service.localdomain))) OK (0 msec) [oracle@dbnode1 admin]$ sqlplus C##TEST/test123@TAC_VIP SQL*Plus: Release 23.26.1.0.0 - Production on Sun Aug 23 00:10:39 2026 Version 23.26.1.0.0 Copyright (c) 1982, 2025, Oracle. All rights reserved. Last Successful login time: Sat Aug 22 2026 23:24:48 +05:30 Connected to: Oracle AI Database 26ai Enterprise Edition Release 23.26.1.0.0 - Production Version 23.26.1.0.0 SQL> set time on 00:10:46 SQL> drop table demo purge; Table dropped. 00:10:52 SQL> create table demo(id number(5), name varchar2(20)); Table created. 00:10:57 SQL> select failover_type, failover_method, failed_over from v$session where sid=sys_context('userenv', 'sid'); FAILOVER_TYPE FAILOVER_M FAI ------------- ---------- --- AUTO BASIC NO 00:11:02 SQL> col HOST_NAME for a45 00:11:07 SQL> select host_name,instance_name from v$instance; HOST_NAME INSTANCE_NAME --------------------------------------------- ---------------- dbnode1.localdomain PR1 00:11:11 SQL> insert into demo values(1,'Apple'); 1 row created. 00:11:18 SQL> insert into demo values(2,'Mango'); 1 row created. 00:11:22 SQL> 00:13:08 SQL> 00:13:09 SQL> 00:13:09 SQL> ............. ............. ............. ............. Please note that I have not executed a COMMIT here. Now, let’s abort or stop this instance from another session and observe how TAC handles the transaction and session recovery. Do not close the above session....let's wait.... From another session, source the environment and stop the DB node instance 1. [oracle@dbnode1 ~]$ . oraenv ORACLE_SID = [oracle] ? PR1 The Oracle base has been set to /u01/app/oracle [oracle@dbnode1 ~]$ env | grep ORA ORACLE_SID=PR1 ORACLE_BASE=/u01/app/oracle ORACLE_HOME=/u01/app/oracle/product/23.0.0/dbhome_1 [oracle@dbnode1 ~]$ date Sun Aug 23 00:11:59 IST 2026 [oracle@dbnode1 ~]$ srvctl stop instance -d PR -i PR1 -force [oracle@dbnode1 ~]$ srvctl status db -d PR Instance PR1 is not running on node dbnode1 Instance PR2 is running on node dbnode2 Node1 DB Alert Log: 2026-08-23T00:12:10.845233+05:30 Stopped service TAC_SERVICE Shutting down ORACLE instance (immediate) (OS id: 18920) Shutdown is initiated by oraagent.bin@dbnode1.localdomain (TNS V1-V3). Stopping background process SMCO. Shutting down instance: further logons disabled 2026-08-23T00:12:11.573462+05:30 Stopping background process CJQ0 2026-08-23T00:12:11.838185+05:30 Process termination requested for pid 18683 (Q002) [source = rdbms], [info = 2] [request issued by pid: 18669, uid: 1002] 2026-08-23T00:12:12.048305+05:30 Stopping background process MMNL. Stopping background process MMON. alter pluggable database all close immediate Completed: alter pluggable database all close immediate 2026-08-23T00:12:12.341715+05:30 PDB$SEED(2):JIT: pid 18920 requesting stop License high water mark = 10 Data Pump shutdown in progress 2026-08-23T00:12:12.745618+05:30 Process termination requested for pid 30516 (oraclePR1) [source = rdbms], [info = 2] [request issued by pid: 18920, uid: 1002] 2026-08-23T00:12:12.746163+05:30 Process termination requested for pid 28768 (PPA7) [source = rdbms], [info = 2] [request issued by pid: 18920, uid: 1002] 2026-08-23T00:12:12.746565+05:30 Process termination requested for pid 16900 (P001) [source = rdbms], [info = 2] [request issued by pid: 18920, uid: 1002] 2026-08-23T00:12:12.746696+05:30 Process termination requested for pid 18559 (P003) [source = rdbms], [info = 2] [request issued by pid: 18920, uid: 1002] 2026-08-23T00:12:12.749201+05:30 Process termination requested for pid 16906 (P002) [source = rdbms], [info = 2] [request issued by pid: 18920, uid: 1002] 2026-08-23T00:12:12.763397+05:30 Process termination requested for pid 16896 (P000) [source = rdbms], [info = 2] [request issued by pid: 18920, uid: 1002] 2026-08-23T00:12:12.776079+05:30 Process termination requested for pid 29073 (PPA6) [source = rdbms], [info = 2] [request issued by pid: 18920, uid: 1002] 2026-08-23T00:12:13.778101+05:30 ALTER DATABASE CLOSE NORMAL /* db agent *//* {0:0:0} */ alter pluggable database all close immediate Completed: alter pluggable database all close immediate alter pluggable database all close immediate Completed: alter pluggable database all close immediate 2026-08-23T00:12:14.006430+05:30 IM on ADG: Start of Empty Journal IM on ADG: End of Empty Journal 2026-08-23T00:12:15.517477+05:30 Stopping change tracking 2026-08-23T00:12:15.618417+05:30 Redo thread 1 internally disabled at seq 35 (LGWR) 2026-08-23T00:12:15.968508+05:30 ARC3 (PID:17083): Archiving disabled T-1.S-35 [krse.c:7451] 2026-08-23T00:12:16.209272+05:30 ARC3 (PID:17083): Archived Log entry 72 added for B-1225547593.T-1.S-35 LOS:0x000000000195dec8 NXS:0x000000000195f6b6 NAB:19950 ID 0xae0d24c6 LAD:1 [krse.c:4883] 2026-08-23T00:12:16.754295+05:30 Thread 1 closed at log sequence 35 Successful close of redo thread 1 2026-08-23T00:12:16.905619+05:30 Entire Buffer Cache invalidation started Entire Buffer Cache invalidation completed Completed: ALTER DATABASE CLOSE NORMAL /* db agent *//* {0:0:0} */ ALTER DATABASE DISMOUNT /* db agent *//* {0:0:0} */ 2026-08-23T00:12:17.919722+05:30 Completed: ALTER DATABASE DISMOUNT /* db agent *//* {0:0:0} */ 2026-08-23T00:12:18.072254+05:30 JIT: pid 18920 requesting stop JIT: pid 18920 requesting stop 2026-08-23T00:12:19.241232+05:30 SHUTDOWN: waiting for detached processes 'CLMN' to terminate. 2026-08-23T00:12:19.584600+05:30 NOTE: Could not deregister group num 1.788566227 2026-08-23T00:12:19.584720+05:30 NOTE: Could not deregister group num 2.789614804 2026-08-23T00:12:19.585118+05:30 NOTE: Could not deregister group num 5.796954839 2026-08-23T00:12:19.585290+05:30 NOTE: Could not deregister group num 4.794857686 Stopping background process RBAL. NOTE: ASMB exiting 2026-08-23T00:12:21.069448+05:30 freeing the pdb enqueue rht Instance shutdown complete (OS id: 18920) Let's verify the local LISTENER status on both nodes by grid user.... [grid@dbnode1 ~]$ lsnrctl status LSNRCTL for Linux: Version 23.26.1.0.0 - Production on 23-AUG-2026 00:16:16 Copyright (c) 1991, 2026, Oracle. All rights reserved. Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=LISTENER))) STATUS of the LISTENER ------------------------ Alias LISTENER Version TNSLSNR for Linux: Version 23.26.1.0.0 - Production Start Date 23-AUG-2026 00:03:27 Uptime 0 days 0 hr. 12 min. 49 sec Trace Level off Security ON: Local OS Authentication SNMP OFF Listener Parameter File /u01/app/23.0.0/grid/network/admin/listener.ora Listener Log File /u01/app/grid/diag/tnslsnr/dbnode1/listener/alert/log.xml Listening Endpoints Summary... (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=LISTENER))) (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=10.20.30.101)(PORT=1521))) (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=10.20.30.103)(PORT=1521))) Services Summary... Service "+ASM" has 1 instance(s). Instance "+ASM1", status READY, has 1 handler(s) for this service... Service "+ASM_DG_ARCH" has 1 instance(s). Instance "+ASM1", status READY, has 1 handler(s) for this service... Service "+ASM_DG_DATA" has 1 instance(s). Instance "+ASM1", status READY, has 1 handler(s) for this service... Service "+ASM_DG_OCR" has 1 instance(s). Instance "+ASM1", status READY, has 1 handler(s) for this service... Service "+ASM_DG_REDO1" has 1 instance(s). Instance "+ASM1", status READY, has 1 handler(s) for this service... Service "+ASM_DG_REDO2" has 1 instance(s). Instance "+ASM1", status READY, has 1 handler(s) for this service... The command completed successfully [grid@dbnode2 ~]$ lsnrctl status LSNRCTL for Linux: Version 23.26.1.0.0 - Production on 23-AUG-2026 00:16:38 Copyright (c) 1991, 2026, Oracle. All rights reserved. Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=LISTENER))) STATUS of the LISTENER ------------------------ Alias LISTENER Version TNSLSNR for Linux: Version 23.26.1.0.0 - Production Start Date 23-AUG-2026 00:07:25 Uptime 0 days 0 hr. 9 min. 13 sec Trace Level off Security ON: Local OS Authentication SNMP OFF Listener Parameter File /u01/app/23.0.0/grid/network/admin/listener.ora Listener Log File /u01/app/grid/diag/tnslsnr/dbnode2/listener/alert/log.xml Listening Endpoints Summary... (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=LISTENER))) (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=10.20.30.102)(PORT=1521))) (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=10.20.30.104)(PORT=1521))) Services Summary... Service "+ASM" has 1 instance(s). Instance "+ASM2", status READY, has 1 handler(s) for this service... Service "+ASM_DG_ARCH" has 1 instance(s). Instance "+ASM2", status READY, has 1 handler(s) for this service... Service "+ASM_DG_DATA" has 1 instance(s). Instance "+ASM2", status READY, has 1 handler(s) for this service... Service "+ASM_DG_OCR" has 1 instance(s). Instance "+ASM2", status READY, has 1 handler(s) for this service... Service "+ASM_DG_REDO1" has 1 instance(s). Instance "+ASM2", status READY, has 1 handler(s) for this service... Service "+ASM_DG_REDO2" has 1 instance(s). Instance "+ASM2", status READY, has 1 handler(s) for this service... Service "4b15f67858842252e063661e140a2ab1.localdomain" has 1 instance(s). Instance "PR2", status READY, has 1 handler(s) for this service... Service "PR.localdomain" has 1 instance(s). Instance "PR2", status READY, has 1 handler(s) for this service... Service "PRXDB.localdomain" has 1 instance(s). Instance "PR2", status READY, has 1 handler(s) for this service... Service "prpdb1.localdomain" has 1 instance(s). Instance "PR2", status READY, has 1 handler(s) for this service... Service "tac_service.localdomain" has 1 instance(s). Instance "PR2", status READY, has 1 handler(s) for this service... The command completed successfully As observed in both the database alert log and the local listener status, the TAC service on Node 1 is down, while it remains available and running on Node 2. Now, let’s return to the original session and verify how Transparent Application Continuity (TAC) seamlessly recovers the session on the surviving node. 00:13:09 SQL> ............. ............. ............. ............. 00:14:50 SQL> 00:14:50 SQL> select * from demo; ID NAME ---------- -------------------- 1 Apple 2 Mango 00:15:01 SQL> 00:15:10 SQL> select host_name,instance_name from v$instance; HOST_NAME INSTANCE_NAME -------------------- ---------------- dbnode2.localdomain PR2 00:15:11 SQL> 00:15:13 SQL> insert into demo values(3,'Banana'); 1 row created. 00:15:27 SQL> commit; Commit complete. 00:15:30 SQL> select * from demo; ID NAME ---------- -------------------- 1 Apple 2 Mango 3 Banana 00:15:37 SQL> As you can see, the original session remained active without displaying any errors or interruption to the user. TAC transparently recovered the session and re-established the connection on the surviving node in the background. This demonstrates that TAC session recovery works seamlessly even when VIP addresses are used in the TNS configuration. Although the transaction had not yet been committed when the original instance became unavailable, TAC successfully replayed the recoverable work on the surviving instance. From the application or user perspective, the failover was transparent, and the user can now execute COMMIT to successfully complete the transaction. |
Step by step configuration of TAC using Public IP Step 1: Lets capture the below details before starting TAC configuration. [grid@dbnode1 ~]$ cat /etc/hosts 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 #Public IP 10.20.30.101 dbnode1.localdomain dbnode1 10.20.30.102 dbnode2.localdomain dbnode2 #Private IP 10.1.2.201 dbnode1-priv.localdomain dbnode1-priv 10.1.2.202 dbnode2-priv.localdomain dbnode2-priv #VIP IP 10.20.30.103 dbnode1-vip.localdomain dbnode1-vip 10.20.30.104 dbnode2-vip.localdomain dbnode2-vip #scan IP 10.20.30.105 dbnode-scan.localdomain dbnode-scan Step 2: Add below Public IP tns entry for TAC service on all cluster nodes. [oracle@dbnode1 ~]$ cat /u01/app/oracle/product/23.0.0/dbhome_1/network/admin/tnsnames.ora TAC_PUB = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = dbnode1)(PORT = 1521)) (ADDRESS = (PROTOCOL = TCP)(HOST = dbnode2)(PORT = 1521)) (CONNECT_DATA = (SERVICE_NAME = tac_service.localdomain) ) ) [oracle@dbnode2 ~]$ cat /u01/app/oracle/product/23.0.0/dbhome_1/network/admin/tnsnames.ora TAC_PUB = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = dbnode1)(PORT = 1521)) (ADDRESS = (PROTOCOL = TCP)(HOST = dbnode2)(PORT = 1521)) (CONNECT_DATA = (SERVICE_NAME = tac_service.localdomain) ) ) #Check the local listener status on both nodes. Since we are using Public addresses in the TNS configuration, verify the status of the local listener on both RAC nodes to ensure that the TAC service is properly registered and running on the appropriate instances. Node1: [grid@dbnode1 ~]$ lsnrctl status LSNRCTL for Linux: Version 23.26.1.0.0 - Production on 23-AUG-2026 00:20:49 Copyright (c) 1991, 2026, Oracle. All rights reserved. Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=LISTENER))) STATUS of the LISTENER ------------------------ Alias LISTENER Version TNSLSNR for Linux: Version 23.26.1.0.0 - Production Start Date 23-AUG-2026 00:03:27 Uptime 0 days 0 hr. 17 min. 22 sec Trace Level off Security ON: Local OS Authentication SNMP OFF Listener Parameter File /u01/app/23.0.0/grid/network/admin/listener.ora Listener Log File /u01/app/grid/diag/tnslsnr/dbnode1/listener/alert/log.xml Listening Endpoints Summary... (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=LISTENER))) (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=10.20.30.101)(PORT=1521))) (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=10.20.30.103)(PORT=1521))) Services Summary... Service "+ASM" has 1 instance(s). Instance "+ASM1", status READY, has 1 handler(s) for this service... Service "+ASM_DG_ARCH" has 1 instance(s). Instance "+ASM1", status READY, has 1 handler(s) for this service... Service "+ASM_DG_DATA" has 1 instance(s). Instance "+ASM1", status READY, has 1 handler(s) for this service... Service "+ASM_DG_OCR" has 1 instance(s). Instance "+ASM1", status READY, has 1 handler(s) for this service... Service "+ASM_DG_REDO1" has 1 instance(s). Instance "+ASM1", status READY, has 1 handler(s) for this service... Service "+ASM_DG_REDO2" has 1 instance(s). Instance "+ASM1", status READY, has 1 handler(s) for this service... Service "4b15f67858842252e063661e140a2ab1.localdomain" has 1 instance(s). Instance "PR1", status READY, has 1 handler(s) for this service... Service "PR.localdomain" has 1 instance(s). Instance "PR1", status READY, has 1 handler(s) for this service... Service "PRXDB.localdomain" has 1 instance(s). Instance "PR1", status READY, has 1 handler(s) for this service... Service "prpdb1.localdomain" has 1 instance(s). Instance "PR1", status READY, has 1 handler(s) for this service... Service "tac_service.localdomain" has 1 instance(s). Instance "PR1", status READY, has 1 handler(s) for this service... The command completed successfully Node2: [grid@dbnode2 ~]$ lsnrctl status LSNRCTL for Linux: Version 23.26.1.0.0 - Production on 23-AUG-2026 00:26:06 Copyright (c) 1991, 2026, Oracle. All rights reserved. Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=LISTENER))) STATUS of the LISTENER ------------------------ Alias LISTENER Version TNSLSNR for Linux: Version 23.26.1.0.0 - Production Start Date 23-AUG-2026 00:07:25 Uptime 0 days 0 hr. 18 min. 41 sec Trace Level off Security ON: Local OS Authentication SNMP OFF Listener Parameter File /u01/app/23.0.0/grid/network/admin/listener.ora Listener Log File /u01/app/grid/diag/tnslsnr/dbnode2/listener/alert/log.xml Listening Endpoints Summary... (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=LISTENER))) (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=10.20.30.102)(PORT=1521))) (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=10.20.30.104)(PORT=1521))) Services Summary... Service "+ASM" has 1 instance(s). Instance "+ASM2", status READY, has 1 handler(s) for this service... Service "+ASM_DG_ARCH" has 1 instance(s). Instance "+ASM2", status READY, has 1 handler(s) for this service... Service "+ASM_DG_DATA" has 1 instance(s). Instance "+ASM2", status READY, has 1 handler(s) for this service... Service "+ASM_DG_OCR" has 1 instance(s). Instance "+ASM2", status READY, has 1 handler(s) for this service... Service "+ASM_DG_REDO1" has 1 instance(s). Instance "+ASM2", status READY, has 1 handler(s) for this service... Service "+ASM_DG_REDO2" has 1 instance(s). Instance "+ASM2", status READY, has 1 handler(s) for this service... Service "4b15f67858842252e063661e140a2ab1.localdomain" has 1 instance(s). Instance "PR2", status READY, has 1 handler(s) for this service... Service "PR.localdomain" has 1 instance(s). Instance "PR2", status READY, has 1 handler(s) for this service... Service "PRXDB.localdomain" has 1 instance(s). Instance "PR2", status READY, has 1 handler(s) for this service... Service "prpdb1.localdomain" has 1 instance(s). Instance "PR2", status READY, has 1 handler(s) for this service... Service "tac_service.localdomain" has 1 instance(s). Instance "PR2", status READY, has 1 handler(s) for this service... The command completed successfully Step 3: Let's connect to the database by TEST user using tns alias "TAC_PUB". [oracle@dbnode1 ~]$ . oraenv ORACLE_SID = [oracle] ? PR1 The Oracle base has been set to /u01/app/oracle [oracle@dbnode1 ~]$ sqlplus C##TEST/test123@TAC_PUB SQL*Plus: Release 23.26.1.0.0 - Production on Sun Aug 23 00:21:27 2026 Version 23.26.1.0.0 Copyright (c) 1982, 2025, Oracle. All rights reserved. Last Successful login time: Sun Aug 23 2026 00:15:01 +05:30 Connected to: Oracle AI Database 26ai Enterprise Edition Release 23.26.1.0.0 - Production Version 23.26.1.0.0 SQL> set time on 00:21:31 SQL> drop table demo purge; Table dropped. 00:21:38 SQL> create table demo(id number(5), name varchar2(20)); Table created. 00:21:42 SQL> select failover_type, failover_method, failed_over from v$session where sid=sys_context('userenv', 'sid'); FAILOVER_TYPE FAILOVER_M FAI ------------- ---------- --- AUTO BASIC NO 00:21:47 SQL> col HOST_NAME for a45 00:21:51 SQL> select host_name,instance_name from v$instance; HOST_NAME INSTANCE_NAME --------------------------------------------- ---------------- dbnode1.localdomain PR1 00:21:56 SQL> insert into demo values(1,'Apple'); 1 row created. 00:22:02 SQL> insert into demo values(2,'Mango'); 1 row created. 00:22:07 SQL> 00:22:11 SQL> 00:22:11 SQL> 00:22:11 SQL> ............. ............. ............. ............. ............. Please note that I have not executed a COMMIT here. Now, let’s abort or stop this instance from another session and observe how TAC handles the transaction and session recovery. Do not close the above session....let's wait.... From another session, source the environment and stop the DB node instance 1. [oracle@dbnode1 ~]$ . oraenv ORACLE_SID = [PR1] ? The Oracle base remains unchanged with value /u01/app/oracle [oracle@dbnode1 ~]$ env | grep ORA ORACLE_SID=PR1 ORACLE_BASE=/u01/app/oracle ORACLE_HOME=/u01/app/oracle/product/23.0.0/dbhome_1 [oracle@dbnode1 ~]$ date Sun Aug 23 00:22:31 IST 2026 [oracle@dbnode1 ~]$ srvctl stop instance -d PR -i PR1 -force [oracle@dbnode1 ~]$ srvctl status db -d PR Instance PR1 is not running on node dbnode1 Instance PR2 is running on node dbnode2 Node1 DB Alert: 2026-08-23T00:22:37.575480+05:30 Stopped service TAC_SERVICE Shutting down ORACLE instance (immediate) (OS id: 37290) Shutdown is initiated by oraagent.bin@dbnode1.localdomain (TNS V1-V3). Stopping background process SMCO. Shutting down instance: further logons disabled 2026-08-23T00:22:38.118782+05:30 Stopping background process CJQ0 2026-08-23T00:22:38.843924+05:30 Stopping background process MMNL. Stopping background process MMON. alter pluggable database all close immediate Completed: alter pluggable database all close immediate 2026-08-23T00:22:39.190804+05:30 PDB$SEED(2):JIT: pid 37290 requesting stop License high water mark = 10 Data Pump shutdown in progress 2026-08-23T00:22:39.597019+05:30 Process termination requested for pid 37103 (P000) [source = rdbms], [info = 2] [request issued by pid: 37290, uid: 1002] 2026-08-23T00:22:39.600759+05:30 Process termination requested for pid 39765 (oraclePR1) [source = rdbms], [info = 2] [request issued by pid: 37290, uid: 1002] 2026-08-23T00:22:39.608029+05:30 Process termination requested for pid 37108 (P002) [source = rdbms], [info = 2] [request issued by pid: 37290, uid: 1002] 2026-08-23T00:22:39.609907+05:30 Process termination requested for pid 37704 (PPA6) [source = rdbms], [info = 2] [request issued by pid: 37290, uid: 1002] 2026-08-23T00:22:39.611041+05:30 Process termination requested for pid 36934 (PPA7) [source = rdbms], [info = 2] [request issued by pid: 37290, uid: 1002] 2026-08-23T00:22:40.622914+05:30 ALTER DATABASE CLOSE NORMAL /* db agent *//* {0:0:0} */ alter pluggable database all close immediate Completed: alter pluggable database all close immediate alter pluggable database all close immediate Completed: alter pluggable database all close immediate 2026-08-23T00:22:41.264985+05:30 IM on ADG: Start of Empty Journal IM on ADG: End of Empty Journal Stopping change tracking 2026-08-23T00:22:41.695295+05:30 Redo thread 1 internally disabled at seq 36 (LGWR) 2026-08-23T00:22:42.001679+05:30 NOTE: ASMB mounting disk group 1 (DG_ARCH) SUCCESS: mounted disk group 1 (DG_ARCH) NOTE: grp 1 disk 0: DG_ARCH_0000 path:/dev/sdg1 2026-08-23T00:22:42.191940+05:30 ARC2 (PID:36982): Archiving disabled T-1.S-36 [krse.c:7451] 2026-08-23T00:22:42.272047+05:30 ARC2 (PID:36982): Archived Log entry 73 added for B-1225547593.T-1.S-36 LOS:0x000000000195f75d NXS:0x0000000001961156 NAB:19990 ID 0xae0d24c6 LAD:1 [krse.c:4883] 2026-08-23T00:22:42.794334+05:30 Thread 1 closed at log sequence 36 Successful close of redo thread 1 2026-08-23T00:22:42.887813+05:30 Entire Buffer Cache invalidation started Entire Buffer Cache invalidation completed Completed: ALTER DATABASE CLOSE NORMAL /* db agent *//* {0:0:0} */ 2026-08-23T00:22:43.954968+05:30 ALTER DATABASE DISMOUNT /* db agent *//* {0:0:0} */ Completed: ALTER DATABASE DISMOUNT /* db agent *//* {0:0:0} */ 2026-08-23T00:22:44.148041+05:30 JIT: pid 37290 requesting stop JIT: pid 37290 requesting stop 2026-08-23T00:22:45.756877+05:30 SHUTDOWN: waiting for detached processes 'CLMN' to terminate. 2026-08-23T00:22:45.853300+05:30 NOTE: Could not deregister group num 1.788566227 2026-08-23T00:22:45.853383+05:30 NOTE: Could not deregister group num 2.789614804 2026-08-23T00:22:45.853417+05:30 NOTE: Could not deregister group num 5.796954839 2026-08-23T00:22:45.853446+05:30 NOTE: Could not deregister group num 4.794857686 Stopping background process RBAL. NOTE: ASMB exiting 2026-08-23T00:22:46.652632+05:30 freeing the pdb enqueue rht Instance shutdown complete (OS id: 37290) Let's verify the local LISTENER status on both nodes by grid user.... [grid@dbnode1 ~]$ lsnrctl status LSNRCTL for Linux: Version 23.26.1.0.0 - Production on 23-AUG-2026 00:23:09 Copyright (c) 1991, 2026, Oracle. All rights reserved. Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=LISTENER))) STATUS of the LISTENER ------------------------ Alias LISTENER Version TNSLSNR for Linux: Version 23.26.1.0.0 - Production Start Date 23-AUG-2026 00:03:27 Uptime 0 days 0 hr. 19 min. 41 sec Trace Level off Security ON: Local OS Authentication SNMP OFF Listener Parameter File /u01/app/23.0.0/grid/network/admin/listener.ora Listener Log File /u01/app/grid/diag/tnslsnr/dbnode1/listener/alert/log.xml Listening Endpoints Summary... (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=LISTENER))) (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=10.20.30.101)(PORT=1521))) (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=10.20.30.103)(PORT=1521))) Services Summary... Service "+ASM" has 1 instance(s). Instance "+ASM1", status READY, has 1 handler(s) for this service... Service "+ASM_DG_ARCH" has 1 instance(s). Instance "+ASM1", status READY, has 1 handler(s) for this service... Service "+ASM_DG_DATA" has 1 instance(s). Instance "+ASM1", status READY, has 1 handler(s) for this service... Service "+ASM_DG_OCR" has 1 instance(s). Instance "+ASM1", status READY, has 1 handler(s) for this service... Service "+ASM_DG_REDO1" has 1 instance(s). Instance "+ASM1", status READY, has 1 handler(s) for this service... Service "+ASM_DG_REDO2" has 1 instance(s). Instance "+ASM1", status READY, has 1 handler(s) for this service... The command completed successfully [grid@dbnode2 ~]$ lsnrctl status LSNRCTL for Linux: Version 23.26.1.0.0 - Production on 23-AUG-2026 00:26:33 Copyright (c) 1991, 2026, Oracle. All rights reserved. Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=LISTENER))) STATUS of the LISTENER ------------------------ Alias LISTENER Version TNSLSNR for Linux: Version 23.26.1.0.0 - Production Start Date 23-AUG-2026 00:07:25 Uptime 0 days 0 hr. 19 min. 8 sec Trace Level off Security ON: Local OS Authentication SNMP OFF Listener Parameter File /u01/app/23.0.0/grid/network/admin/listener.ora Listener Log File /u01/app/grid/diag/tnslsnr/dbnode2/listener/alert/log.xml Listening Endpoints Summary... (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=LISTENER))) (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=10.20.30.102)(PORT=1521))) (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=10.20.30.104)(PORT=1521))) Services Summary... Service "+ASM" has 1 instance(s). Instance "+ASM2", status READY, has 1 handler(s) for this service... Service "+ASM_DG_ARCH" has 1 instance(s). Instance "+ASM2", status READY, has 1 handler(s) for this service... Service "+ASM_DG_DATA" has 1 instance(s). Instance "+ASM2", status READY, has 1 handler(s) for this service... Service "+ASM_DG_OCR" has 1 instance(s). Instance "+ASM2", status READY, has 1 handler(s) for this service... Service "+ASM_DG_REDO1" has 1 instance(s). Instance "+ASM2", status READY, has 1 handler(s) for this service... Service "+ASM_DG_REDO2" has 1 instance(s). Instance "+ASM2", status READY, has 1 handler(s) for this service... Service "4b15f67858842252e063661e140a2ab1.localdomain" has 1 instance(s). Instance "PR2", status READY, has 1 handler(s) for this service... Service "PR.localdomain" has 1 instance(s). Instance "PR2", status READY, has 1 handler(s) for this service... Service "PRXDB.localdomain" has 1 instance(s). Instance "PR2", status READY, has 1 handler(s) for this service... Service "prpdb1.localdomain" has 1 instance(s). Instance "PR2", status READY, has 1 handler(s) for this service... Service "tac_service.localdomain" has 1 instance(s). Instance "PR2", status READY, has 1 handler(s) for this service... The command completed successfully As observed in both the database alert log and the local listener status, the TAC service on Node 1 is down, while it remains available and running on Node 2. Now, let’s return to the original session and verify how Transparent Application Continuity (TAC) seamlessly recovers the session on the surviving node. 00:22:11 SQL> 00:22:12 SQL> 00:22:12 SQL> 00:22:12 SQL> 00:22:12 SQL> 00:23:29 SQL> insert into demo values(3,'Banana'); 1 row created. 00:23:44 SQL> 00:23:45 SQL> select * from demo; ID NAME ---------- -------------------- 1 Apple 2 Mango 3 Banana 00:23:57 SQL> 00:23:58 SQL> select host_name,instance_name from v$instance; HOST_NAME INSTANCE_NAME ------------------------- ---------------- dbnode2.localdomain PR2 00:24:00 SQL> commit; Commit complete. 00:24:03 SQL> As you can see, the original session remained active without displaying any errors or interruption to the user. TAC transparently recovered the session and re-established the connection on the surviving node in the background. This demonstrates that TAC session recovery works seamlessly even when Public addresses are used in the TNS configuration. Although the transaction had not yet been committed when the original instance became unavailable, TAC successfully replayed the recoverable work on the surviving instance. From the application or user perspective, the failover was transparent, and the user can now execute COMMIT to successfully complete the transaction. |
🔗JDBC Connection Strings for Application Configuration: The following JDBC Thin connection strings can be used by an application to connect to the Oracle RAC database service. 🛠️Connection Using SCAN: jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=dbnode-scan)(PORT=1530))(CONNECT_DATA=(SERVICE_NAME=tac_service.localdomain))) 🛠️Connection Using Node VIPs: jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=dbnode1-vip)(PORT=1521))(ADDRESS=(PROTOCOL=TCP)(HOST=dbnode2-vip)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=tac_service.localdomain))) 🛠️Connection Using Public Hostnames: jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=dbnode1)(PORT=1521))(ADDRESS=(PROTOCOL=TCP)(HOST=dbnode2)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=tac_service.localdomain))) 🎯 Final Conclusion: TAC with SCAN, VIP, and Public IP Addresses Our testing demonstrates that Oracle Transparent Application Continuity (TAC) can provide a highly resilient and transparent application experience across different Oracle RAC connection configurations. Whether the client connection is established using SCAN, VIP, or public IP addresses, the fundamental objective remains the same: maintain application continuity when an RAC instance becomes unavailable. |
⚠️ Important Note: Application-Level TAC Testing: The above TAC testing was conducted manually using SQL*Plus, and the TAC functionality worked successfully without any issues. However, it is strongly recommended to perform thorough application-level testing using the actual JDBC connection string and application workload before implementing TAC in the production database. This recommendation is based on a compatibility issue encountered during earlier testing with an Oracle Database 19c environment. In that case, the source client application encountered the following replay error: ORA-25412: transaction replay disabled by call to OCIbindArrayOfStruct The issue was related to a compatibility limitation in the client/application interaction with TAC and has been addressed in Oracle AI Database 26ai. Therefore, successful TAC validation through SQL*Plus alone should not be considered sufficient for production readiness. The application should be thoroughly tested with its actual JDBC driver, connection pool, JDBC connection string, transaction patterns, and representative workload, including planned and unplanned failover scenarios. This application-level validation is important to confirm that transaction replay behaves as expected and that there are no application- or driver-specific compatibility issues before enabling TAC in the actual production environment. |
Thanks for reading this post ! Please comment if you like this post ! Click on FOLLOW to get next blog updates !

