Bo's Oracle Station

【博客文章2023】在Windows上利用java程序来连接RAC主备数据库体验跨库Transaction Guard功能

2023-12-6 10:40| 发布者: admin| 查看: 54| 评论: 0|原作者: Bo Tang

摘要: 在Windows上利用java程序来连接RAC主备数据库体验跨库Transaction Guard功能。
【博客文章2023】在Windows上利用java程序来连接RAC主备数据库体验跨库Transaction Guard功能

Author: Bo Tang

1. 带有GDS的MAA起始环境:


    实验的起始环境是:在主机station5.lab.example.com和主机station6.lab.example.com上运行着名为c01orcl.example.com的RAC数据库(Policy-managed,版本19.3.0);在主机station7.lab.example.com和主机station8.lab.example.com上运行着名为c02orcl.example.com的RAC数据库(Policy-managed,版本19.3.0.)。起始时,c02orcl.example.com为主库,c01orcl.example.com为物理备库。    
   dataguard状态正常

DGMGRL>  show configuration verbose;

Configuration - dg_config

  Protection Mode: MaxAvailability
  Members:
  c02orcl - Primary database
    c01orcl - (*) Physical standby database

  (*) Fast-Start Failover target

  Properties:
    FastStartFailoverThreshold      = '30'
    OperationTimeout                = '30'
    TraceLevel                      = 'USER'
    FastStartFailoverLagLimit       = '0'
    CommunicationTimeout            = '180'
    ObserverReconnect               = '0'
    FastStartFailoverAutoReinstate  = 'TRUE'
    FastStartFailoverPmyShutdown    = 'TRUE'
    BystandersFollowRoleChange      = 'ALL'
    ObserverOverride                = 'FALSE'
    ExternalDestination1            = ''
    ExternalDestination2            = ''
    PrimaryLostWriteAction          = 'CONTINUE'
    ConfigurationWideServiceName    = 'c01orcl_CFG'

Fast-Start Failover: Enabled in Zero Data Loss Mode
  Lag Limit:          0 seconds
  Threshold:          30 seconds
  Active Target:      c01orcl
  Potential Targets:  "c01orcl"
    c01orcl    valid
  Observer:           DESKTOP-KU8CSV1
  Shutdown Primary:   TRUE
  Auto-reinstate:     TRUE
  Observer Reconnect: (none)
  Observer Override:  FALSE

Configuration Status:
SUCCESS

 

    在该dataguard环境之上还配置有全局数据服务:station5.lab.example.com主机上运行有gsm(gsm名字为gsmc01orcl,其region为regc01orcl);station7.lab.example.com主机上运行有gsm(gsm名字为gsmc02orcl,其region为regc02orcl)。GDS的pool为sales,管理着dataguard broker,并运行着支持支持APPLICATION CONTINUITY和TRANSACTION GUARD全局服务:gpserv3.sales.oracloud,它的创建通过:

add service -service gpserv3 -gdspool sales –preferred_all –role PRIMARY -rlbgoal  SERVICE_TIME -clbgoal LONG -failovertype TRANSACTION -failovermethod BASIC -notification TRUE -commit_outcome TRUE -retention 86400 -replay_init_time 1800 -pdbname pdb1_1-server_pool  servpool -cardinality  UNIFORM


 

GDSCTL> config

Regions
------------------------
regc01orcl                    
regc02orcl                    
regionora                     

GSMs
------------------------
gsmc01orcl                    
gsmc02orcl                    

GDS pools
------------------------
dbpoolora                     
sales                         

Databases
------------------------
c01orcl                       
c02orcl                       

Services
------------------------
gpserv3                       

GDSCTL pending requests
------------------------
Command                       Object                        Status                        
-------                       ------                        ------                        

Global properties
------------------------
Name: oradbcloud
Master GSM: gsmc02orcl
DDL sequence #: 0

 

GDSCTL>  config database
Name                Pool                Status    State       Region    Availability 
----                ----                ------    -----       ------    ------------ 
c01orcl             sales               Ok        none        regc01orc ONLINE       
                                                              l                      
c02orcl             sales               Ok        none        regc02orc READ ONLY     

 

GDSCTL>  config gsm    
Name      Region    ENDPOINT                                                    
----      ------    --------                                                    
gsmc01orc regc01orc (ADDRESS=(HOST=station5.lab.example.com)(PORT=1571)(PROTOCO 
l         l         L=tcp))                                                     
gsmc02orc regc02orc (ADDRESS=(HOST=station7.lab.example.com)(PORT=1572)(PROTOCO 
l         l         L=tcp))     

 

GDSCTL> config region

Name                          Buddy                         
----                          -----                         
regc01orcl                                                  
regc02orcl                                                  
regionora     

 

[oracle@station7 ~]$ srvctl stop database -d c02orcl -o abort

GDSCTL>  config service


Name           Network name                  Pool           Started Preferred all 
----           ------------                  ----           ------- ------------- 
gpserv3        gpserv3.sales.oradbcloud      sales          Yes     Yes           

GDSCTL> status database
Alert: GSM listener rejected database registration.
Alert: catalog database is not registered on GSM listener.
Database: "c01orcl" Registered: Y State: Ok ONS: Y. Role: PRIMARY Instances: 1 Region: regc01orcl
Alert: Data Guard observer is not running.
   Service: "gpserv3" Globally started: Y Started: Y
            Scan: Y Enabled: Y Preferred: Y
   Registered instances:
     sales%2
Database: "c02orcl" Registered: Y State: Ok ONS: Y. Role: PH_STNDBY Instances: 1 Region: regc02orcl
   Service: "gpserv3" Globally started: Y Started: N
            Scan: Y Enabled: Y Preferred: Y
   Registered instances:
     sales%11


GDSCTL> status gsm
Alias                     GSMC01ORCL
Version                   19.0.0.0.0
Start Date                08-DEC-2023 18:50:19
Trace Level               off
Listener Log File         /u01/app/oracle/diag/gsm/station5/gsmc01orcl/alert/log.xml
Listener Trace File       /u01/app/oracle/diag/gsm/station5/gsmc01orcl/trace/ora_48856_139760136588352.trc
Endpoint summary          (ADDRESS=(HOST=station5.lab.example.com)(PORT=1571)(PROTOCOL=tcp))
GSMOCI Version            3.0.180702
Mastership                N
Connected to GDS catalog  Y
Process Id                48862
Number of reconnections   0
Pending tasks.     Total  0
Tasks in  process. Total  0
Alert: GSM listener rejected database registration.
Alert: catalog database is not registered on GSM listener.
Regional Mastership       TRUE
Total messages published  496
Time Zone                 +08:00
Orphaned Buddy Regions:   
     None
GDS region                regc01orcl
Network metrics:
   Region: regc02orcl Network factor:0


GDSCTL> status service
Service "gpserv3.sales.oradbcloud" has 1 instance(s). Affinity: ANYWHERE
   Instance "sales%2", name: "c01orcl_2", db: "C01ORCL", region: "regc01orcl", status: ready.

GDSCTL> 


2. 用一个通用的JAVA程序重新包装问题代码:

    如果需要执行编写得很差的3万代码(就是把表t04209_uname的uvalue值加1,共执行3万次)如:

update hr.t04209_uname set uvalue=2 where uname='a1';

update hr.t04209_uname set uvalue=3 where uname='a2';

update hr.t04209_uname set uvalue=4 where uname='a3';

update hr.t04209_uname set uvalue=5 where uname='a4';

update hr.t04209_uname set uvalue=6 where uname='a5';

......


    改写以上代码成一个存储过程:

create or replace procedure hr.proctest1

as

begin

update hr.t04209_uname set uvalue=2 where uname='a1';

update hr.t04209_uname set uvalue=3 where uname='a2';

update hr.t04209_uname set uvalue=4 where uname='a3';

update hr.t04209_uname set uvalue=5 where uname='a4';

update hr.t04209_uname set uvalue=6 where uname='a5';

......

end;

/


    调用Oracle Universal Connection Pool线程管理的通用JAVA程序重新包装问题代码:

package Test;

import javax.sql.DataSource;
import java.sql.*;
import oracle.ucp.jdbc.ValidConnection;
import oracle.ucp.jdbc.PoolDataSource;
import oracle.ucp.jdbc.oracle.OracleJDBCConnectionPoolStatistics;
import java.util.Random;
import java.text.SimpleDateFormat;
import java.text.DateFormat;
import java.util.Calendar;

class Worker implements Runnable {
  PoolDataSource ds;
  Random random;
  Boolean cpuIntensive;
  Worker(PoolDataSource _ds) {
    ds = _ds;
    random = new Random();
  }
 
  void databaseWorkload(Connection c) throws SQLException {
//准备SQL语句
//只循环1次,这样写便于以后更改重复执行的次数
    for(int i=0;i<1;i++) 
    {
       PreparedStatement pstmt = c.prepareStatement("begin hr.proctest1; end;");
       try{
            pstmt.executeUpdate();
            if (Test.VERBOSE) { System.out.println("Adding row to test1"); }

        } catch(SQLException insertsqlex)
        {
         if (insertsqlex instanceof SQLIntegrityConstraintViolationException) {
            if (insertsqlex.getMessage().startsWith("ORA-00001: unique constraint (HR.PK_TEST1) violated")){
              System.out.println("in catch block for constraint violation\n");
            }
         }
         else throw insertsqlex;
       }
      pstmt.close();
    }
     // c.rollback();
     c.commit();
  }
  
  public void run() {
    long counter = 0;
     boolean retry = false;
     Connection c = null;
     DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:MM:SS");
     Calendar cal = Calendar.getInstance();
     
      long nanoTimeStart=0,timeSpentOnDb = 0;
      try {
        c = ds.getConnection();
        // Make sure auto commit if off:
        c.setAutoCommit(false);

          ResultSet rs;
          Statement stmt = c.createStatement();
          
          rs =

           stmt.executeQuery("select '... Connected to '||sys_context('userenv','instance_name') from dual");
  
          while (rs.next()) { 
              // Only display for VERBOSE operation 
              if (Test.VERBOSE) { System.out.println( dateFormat.format(cal.getTime()) + "  " + rs.getString(1)); }
          }
          rs.close();
          stmt.close();
          */
           if (retry) {
              System.out.println(" Application driven connection retry succeeded");
              retry = false;
           }

        nanoTimeStart = System.nanoTime();
        
    
        if (Test.VERBOSE) { System.out.println("Executing databaseWorkload()"); }
        databaseWorkload(c);
        
      } catch (SQLException ea) {
/* 有了AC,应用开发人员就不用编写代码来恢复事务*/   
        try {
         if (c == null ||!((ValidConnection)c).isValid()){
          ea.printStackTrace();
          System.out.println("Application error handling: attempting to get a new connection "+ea.getMessage()+".");
           c.close();
           String fcfInfo = ((OracleJDBCConnectionPoolStatistics) ds.getStatistics()).getFCFProcessingInfoProcessedOnly();
           System.out.println("FCF information: " + fcfInfo);
            retry = true;
         } else {
          System.out.println("unknown exception: " + ea);
          }
        }catch (SQLException ea1) {}
        //
        synchronized (Test.statsLock) {
          Test.nbOfExceptions++;
          if(Test.applicationCrashOnErrors && Test.nbOfExceptions > 20)
          {
            System.err.println("20 fatal exceptions.");
            System.err.println("");
            System.err.println("*** APPLICATION CRASHED ***");
            System.err.println("");
            System.exit(1);
          }
        }
        if(Test.VERBOSE) {
          ea.printStackTrace();
          
          System.err.println("."+ea.getMessage()+".");
        }
        
      } finally {
        timeSpentOnDb = (System.nanoTime()-nanoTimeStart)/1000000; // in ms
        try {
          if (c != null) {
            c.close();
            if (Test.VERBOSE) { System.out.println("Closed connection"); }
          }
        } catch (SQLException ea) {}
      }

   
      if(counter > 0) {
        synchronized (Test.statsLock) {
          Test.operationsCompleted++;
          
          Test.timeSpentOnDb += timeSpentOnDb;
        }
      }

      if (Test.threadThinkTime > 0) {
        // Introduce delay between requests for processing webpages
        long timeToSleep = Test.threadThinkTime +
          random.nextInt((Test.threadThinkTime<10)?10:Test.threadThinkTime/10);
        try {
          Thread.sleep(timeToSleep);
        } catch (Exception ea) {}
      }
      counter++;
    }

  }

    编译后在windows上执行lib.zip
    其中runreplay.bat的内容如下:

C:\app\oracle\jdk\bin\java -classpath lib\* Test.Test ac_replay.properties


3. 在windows上运行以上的runreplay.bat,并模拟数据库故障(运行过程中切换数据库):

    

    定位以上会话:


    中途关闭正在执行的PRIMARY数据库:

 

[oracle@station7 ~]$ srvctl stop database -d c02orcl -o abort


   观察windows客户端的响应,同时观察Fast-start Failover进行broker failover的日志:


 

Switchover: Complete - Database mounted as primary
TMI: kcv_commit_to_so_to_primary Switchover from physical END 2023-12-08 18:23:42.508076
TMI: dbsdrv failover to target END 2023-12-08 18:23:42.508466
Failover completed with No-Data-Loss.
Completed: ALTER DATABASE FAILOVER TO c01orcl
2023-12-08T18:23:43.263533+08:00
ALTER DATABASE SET STANDBY DATABASE TO MAXIMIZE AVAILABILITY
Completed: ALTER DATABASE SET STANDBY DATABASE TO MAXIMIZE AVAILABILITY
ALTER DATABASE OPEN
2023-12-08T18:23:43.340287+08:00
TMI: adbdrv open database BEGIN 2023-12-08 18:23:43.340110
Data Guard Broker initializing...
2023-12-08T18:23:43.416600+08:00
idle dispatcher 'D000' terminated, pid = (53, 1)
2023-12-08T18:23:43.709647+08:00
This instance was first to open
Ping without log force is disabled:
  not an Exadata system.
2023-12-08T18:23:44.449256+08:00
Crash Recovery excluding pdb 2 which was cleanly closed.
Picked broadcast on commit scheme to generate SCNs
2023-12-08T18:23:44.867669+08:00
Assigning activation ID 1199281709 (0x477b962d)
LGWR (PID:30024): Primary database is in MAXIMUM AVAILABILITY mode
LGWR (PID:30024): LAD:1 is not serviced by LGWR
Redo log for group 1, sequence 1 is not located on DAX storage
Thread 1 opened at log sequence 1
  Current log# 1 seq# 1 mem# 0: +DATA/C01ORCL/ONLINELOG/group_1.292.1147802483
  Current log# 1 seq# 1 mem# 1: +FRA/C01ORCL/ONLINELOG/group_1.258.1147802485
Successful open of redo thread 1
2023-12-08T18:23:45.386485+08:00
MTTR advisory is disabled because FAST_START_MTTR_TARGET is not set
stopping change tracking
2023-12-08T18:23:45.436139+08:00
ALTER SYSTEM SET remote_listener='scan5.cluster5.lab.example.com:1521' SCOPE=MEMORY SID='c01orcl_2';
2023-12-08T18:23:45.467258+08:00
ALTER SYSTEM SET listener_networks='' SCOPE=MEMORY SID='c01orcl_2';
2023-12-08T18:23:45.497253+08:00
ARC3 (PID:30822): Becoming the 'no SRL' ARCH
2023-12-08T18:23:45.546854+08:00
TT03 (PID:33702): Sleep 5 seconds and then try to clear SRLs in 2 time(s)
2023-12-08T18:23:46.622499+08:00
Undo initialization recovery: err:0 start: 68139040 end: 68140061 diff: 1021 ms (1.0 seconds)

............
2023-12-08T18:24:57.184221+08:00
PDB1_1(3):[32846] Successfully onlined Undo Tablespace 5.
PDB1_1(3):Undo initialization online undo segments: err:0 start: 68205995 end: 68210626 diff: 4631 ms (4.6 seconds)
PDB1_1(3):Undo initialization finished serial:0 start:68205908 end:68210703 diff:4795 ms (4.8 seconds)
2023-12-08T18:24:58.183320+08:00
PDB1_1(3):Database Characterset for PDB1_1 is AL32UTF8
2023-12-08T18:25:18.172214+08:00
PDB1_1(3):Opening pdb with no Resource Manager plan active
2023-12-08T18:25:27.872314+08:00
PDB1_1(3):joxcsys_required_dirobj_exists: directory object exists with required path /u01/app/oracle/product/19.3.0/dbhome_1/javavm/admin/, pid 32846 cid 3
2023-12-08T18:25:29.045021+08:00
Pluggable database PDB1_1 opened read write
2023-12-08T18:25:31.453890+08:00
TMI: adbdrv open database END 2023-12-08 18:25:31.453170
Starting background process CJQ0
2023-12-08T18:25:31.708213+08:00
CJQ0 started with pid=111, OS id=35176
Completed: ALTER DATABASE OPEN
ALTER PLUGGABLE DATABASE ALL OPEN
Completed: ALTER PLUGGABLE DATABASE ALL OPEN
2023-12-08T18:25:32.696283+08:00
ALTER SYSTEM SET fal_server='' SCOPE=BOTH;
2023-12-08T18:25:32.910365+08:00
Failover succeeded. Primary database is now C01ORCL.


   实现了跨库Transaction Guard功能


    回话和事务都漂移到了新主库c01orcl,最终也正好修改了3万行。

路过

雷人

握手

鲜花

鸡蛋

QQ|手机版|Bo's Oracle Station   

GMT+8, 2024-2-21 21:31 , Processed in 0.036008 second(s), 21 queries .

返回顶部