Se stai utilizzando un database 11g, puoi utilizzare il DBMS_XA
pacchetto
per consentire a una sessione di partecipare a una transazione avviata dalla prima sessione. Come dimostra Tim Hall, puoi avviare una transazione in una sessione, unirti a quella transazione da un'altra sessione e leggere le modifiche non vincolate apportate alla transazione. Sfortunatamente, tuttavia, ciò non aiuterà con le variabili di sessione (supponendo che "variabile di sessione" significhi variabile di pacchetto con ambito di sessione).
Crea il pacchetto e la tabella:
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;
Nella sessione 1, avviamo una transazione globale, impostiamo la variabile del pacchetto e inseriamo una riga nella tabella prima di sospendere la transazione globale (che consente a un'altra sessione di riprenderla)
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.
Nella sessione 2, riprendiamo la transazione globale, leggiamo dalla tabella, leggiamo la variabile di sessione e terminiamo la transazione globale. Nota che la query sulla tabella vede la riga che abbiamo inserito ma la modifica della variabile del pacchetto non è visibile.
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.
Per condividere lo stato della sessione tra le sessioni, sarebbe possibile utilizzare un contesto dell'applicazione globale
piuttosto che usare le variabili del pacchetto? Potresti combinarlo con il DBMS_XA
pacchetti se vuoi leggere sia le tabelle del database che lo stato della sessione.
Crea il contesto e il pacchetto con getter e 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;
Nella sessione 1, imposta il valore della variabile di contesto G_VAR
a 47 per la sessione 12345
begin
pkg_foo.set_var( 12345, 47 );
end;
Ora, la sessione 2 può leggere il valore dal contesto
1* select pkg_foo.get_var( 12345 ) from dual
SQL> /
PKG_FOO.GET_VAR(12345)
----------------------
47