Can I support one Oracle session from two oci clients?

Is it possible to connect to Oracle (via OCI) from one process and then connect to one database session from another process?

In my current application, there are two ways to access the database: synchronous and asynchronous (using a separate process, exchanging through sockets). The problem is that the two methods implement different sessions.

If I try, for example. update in one session, then try to update the same table from another session without committing, I get a hang on an OCI call.

Even worse, if a session variable is set from one session, the other session does not see it (this is exactly what the name says ...).

+6
source share
1 answer

If you are using the 11g database, you can use the DBMS_XA package DBMS_XA that one session can join the transaction started by the first session. As Tim Hall demonstrates, you can start a transaction in one session, join this transaction from another session and read the uncommitted changes made to the transaction. Unfortunately, however, this does not help with session variables (it is assumed that “session variable” means a packet variable that has a session scope).

Create a package and a 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 pausing the global transaction (which allows it to resume another session).

 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 complete the global transaction. Note that the query for the table sees the row we inserted, but the change in the package variable 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 sessions, is it possible to use a global context instead of using package variables? You can combine this with DBMS_XA packages if you want to read both the database tables and the session state.

Create context and package using 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 G_VAR context G_VAR to 47 for session 12345

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

Session 2 can now read the value from context

  1* select pkg_foo.get_var( 12345 ) from dual SQL> / PKG_FOO.GET_VAR(12345) ---------------------- 47 
+6
source

Source: https://habr.com/ru/post/910176/


All Articles