can I maintain one Oracle session from two oci clients?

后端 未结 1 835
孤城傲影
孤城傲影 2021-01-12 15:57

Is there a possibility to connect to Oracle (via OCI) from one process, then connect on the same database session from another process?

In my current app, there are

相关标签:
1条回答
  • 2021-01-12 16:14

    If you are using an 11g database, you could use the DBMS_XA package to allow one session to to join a transaction started by the first session. As Tim Hall deomonstrates, you can start a transaction in one session, join that transaction from another session, and read the uncommitted changes made in the transaction. Unfortunately, however, that is not going to help with session variables (assuming that "session variable" means package variable that have session scope).

    Create the package and the table:

    CREATE TABLE foo( col1 NUMBER );
    
    create or replace package pkg_foo
    as
      g_var number;
      procedure set_var( p_in number );
    end;
    
    create or replace package body pkg_foo
    as
      procedure set_var( p_in number )
      as
      begin
        g_var := p_in;
      end;
    end;
    

    In Session 1, we start a global transaction, set the package variable, and insert a row into the table before suspending the global transaction (which allows another session to resume it)

    SQL> ed
    Wrote file afiedt.buf
    
      1  declare
      2    l_xid dbms_xa_xid := dbms_xa_xid( 1 );
      3    l_ret integer;
      4  begin
      5    l_ret := dbms_xa.xa_start( l_xid, dbms_xa.tmnoflags );
      6    pkg_foo.set_var(42);
      7    dbms_output.put_line( 'Set pkg_foo.g_var to ' || pkg_foo.g_var );
      8    insert into foo values( 42 );
      9    l_ret := dbms_xa.xa_end( l_xid, dbms_xa.tmsuspend );
     10* end;
    SQL> /
    Set pkg_foo.g_var to 42
    
    PL/SQL procedure successfully completed.
    

    In session 2, we resume the global transaction, read from the table, read the session variable, and end the global transaction. Note that the query against the table sees the row we inserted but the package variable change is not visible.

    SQL> ed
    Wrote file afiedt.buf
    
      1  declare
      2    l_xid dbms_xa_xid := dbms_xa_xid( 1 );
      3    l_ret integer;
      4    l_col1 integer;
      5  begin
      6    l_ret := dbms_xa.xa_start( l_xid, dbms_xa.tmresume );
      7    dbms_output.put_line( 'Read pkg_foo.g_var as ' || pkg_foo.g_var );
      8    select col1 into l_col1 from foo;
      9    dbms_output.put_line( 'Read COL1 from FOO as ' || l_col1 );
     10    l_ret := dbms_xa.xa_end( l_xid, dbms_xa.tmsuccess );
     11* end;
    SQL> /
    Read pkg_foo.g_var as
    Read COL1 from FOO as 42
    
    PL/SQL procedure successfully completed.
    

    To share session state between the sessions, would it be possible to use a global application context rather than using package variables? You could combine that with the DBMS_XA packages if you want to read both database tables and session state.

    Create the context and the package with the getter and setter

    CREATE CONTEXT my_context
      USING pkg_foo
      ACCESSED GLOBALLY;
    
    create or replace package pkg_foo
    as
      procedure set_var( p_session_id in number,
                         p_in         in number );
      function get_var( p_session_id in number )
        return number;
    end;
    
    create or replace package body pkg_foo
    as
      procedure set_var( p_session_id in number,
                         p_in         in number )
      as
      begin
        dbms_session.set_identifier( p_session_id );
        dbms_session.set_context( 'MY_CONTEXT', 'G_VAR', p_in, null, p_session_id );
      end;
      function get_var( p_session_id in number )
        return number
      is
      begin
        dbms_session.set_identifier( p_session_id );
        return sys_context('MY_CONTEXT', 'G_VAR');
      end;
    end;
    

    In session 1, set the value of the context variable G_VAR to 47 for session 12345

    begin
      pkg_foo.set_var( 12345, 47 );
    end;
    

    Now, session 2 can read the value from the context

      1* select pkg_foo.get_var( 12345 ) from dual
    SQL> /
    
    PKG_FOO.GET_VAR(12345)
    ----------------------
                        47
    
    0 讨论(0)
提交回复
热议问题