Если вы используете базу данных 11g, вы можете использовать пакет DBMS_XA
, чтобы разрешить одному сеансу присоединиться к транзакции, запущенной первым сеансом.Как показывает Тим Холл, вы можете запустить транзакцию в одном сеансе, присоединиться к ней из другого сеанса и прочитать незафиксированные изменения, внесенные в транзакцию.К сожалению, однако, это не поможет с переменными сеанса (при условии, что «переменная сеанса» означает переменную пакета, имеющую область сеанса).
Создайте пакет и таблицу:
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;
В сеансе 1 мы запускаем глобальную транзакцию, устанавливаем переменную пакета и вставляем строку в таблицу, прежде чем приостановить глобальную транзакцию (что позволяет другому сеансу возобновить ее)
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.
В сеансе 2,мы возобновляем глобальную транзакцию, читаем из таблицы, читаем переменную сеанса и завершаем глобальную транзакцию.Обратите внимание, что запрос к таблице видит вставленную нами строку, но изменение переменной пакета не отображается.
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.
Чтобы разделить состояние сеанса между сеансами, можно ли использовать глобальное приложение контекст вместо использования переменных пакета?Вы можете комбинировать это с пакетами DBMS_XA
, если хотите прочитать таблицы базы данных и состояние сеанса.
Создать контекст и пакет с помощью метода получения и установки
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;
В сеансе1, установите значение переменной контекста G_VAR
равным 47 для сеанса 12345
begin
pkg_foo.set_var( 12345, 47 );
end;
Теперь сеанс 2 может считывать значение из контекста
1* select pkg_foo.get_var( 12345 ) from dual
SQL> /
PKG_FOO.GET_VAR(12345)
----------------------
47