Oracle
 sql >> Datenbank >  >> RDS >> Oracle

kann ich eine Oracle-Session von zwei oci-Clients aus unterhalten?

Wenn Sie eine 11g-Datenbank verwenden, können Sie den DBMS_XA Paket um einer Sitzung zu erlauben, an einer Transaktion teilzunehmen, die von der ersten Sitzung gestartet wurde. Wie Tim Hall demonstriert, können Sie eine Transaktion in einer Sitzung starten, dieser Transaktion aus einer anderen Sitzung beitreten und die nicht festgeschriebenen Änderungen lesen, die in der Transaktion vorgenommen wurden. Leider hilft das jedoch nicht bei Sitzungsvariablen (vorausgesetzt, dass "Sitzungsvariable" Paketvariablen bedeutet, die einen Sitzungsbereich haben).

Erstellen Sie das Paket und die Tabelle:

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 Sitzung 1 starten wir eine globale Transaktion, setzen die Paketvariable und fügen eine Zeile in die Tabelle ein, bevor wir die globale Transaktion unterbrechen (was einer anderen Sitzung erlaubt, sie fortzusetzen)

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 Sitzung 2 nehmen wir die globale Transaktion wieder auf, lesen aus der Tabelle, lesen die Sitzungsvariable und beenden die globale Transaktion. Beachten Sie, dass die Abfrage der Tabelle die von uns eingefügte Zeile sieht, aber die Änderung der Paketvariablen nicht sichtbar ist.

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.

Um den Sitzungsstatus zwischen den Sitzungen auszutauschen, wäre es möglich, einen globaler Anwendungskontext anstatt Paketvariablen zu verwenden? Sie könnten das mit dem DBMS_XA kombinieren Pakete, wenn Sie sowohl Datenbanktabellen als auch Sitzungsstatus lesen möchten.

Erstellen Sie den Kontext und das Paket mit Getter und 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;

Setzen Sie in Sitzung 1 den Wert der Kontextvariablen G_VAR bis 47 für Sitzung 12345

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

Jetzt kann Sitzung 2 den Wert aus dem Kontext lesen

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

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