sql >> Base de Datos >  >> RDS >> Oracle

¿puedo mantener una sesión de Oracle desde dos clientes oci?

Si está usando una base de datos 11g, podría usar el DBMS_XA paquete para permitir que una sesión se una a una transacción iniciada por la primera sesión. Como demuestra Tim Hall, puede iniciar una transacción en una sesión, unirse a esa transacción desde otra sesión y leer los cambios no confirmados realizados en la transacción. Desafortunadamente, sin embargo, eso no va a ayudar con las variables de sesión (asumiendo que "variable de sesión" significa variable de paquete que tiene alcance de sesión).

Cree el paquete y la tabla:

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;

En la Sesión 1, comenzamos una transacción global, configuramos la variable del paquete e insertamos una fila en la tabla antes de suspender la transacción global (lo que permite que otra sesión la reanude)

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.

En la sesión 2, reanudamos la transacción global, leemos de la tabla, leemos la variable de sesión y finalizamos la transacción global. Tenga en cuenta que la consulta contra la tabla ve la fila que insertamos pero el cambio de variable del paquete no es 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.

Para compartir el estado de la sesión entre las sesiones, ¿sería posible usar un contexto de aplicación global en lugar de usar variables de paquete? Podrías combinar eso con el DBMS_XA paquetes si desea leer tanto las tablas de la base de datos como el estado de la sesión.

Cree el contexto y el paquete con getter y 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;

En la sesión 1, establezca el valor de la variable de contexto G_VAR a 47 para la sesión 12345

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

Ahora, la sesión 2 puede leer el valor del contexto

  1* select pkg_foo.get_var( 12345 ) from dual
SQL> /

PKG_FOO.GET_VAR(12345)
----------------------
                    47