sql >> Database >  >> RDS >> Oracle

kan ik één Oracle-sessie van twee oci-clients onderhouden?

Als u een 11g-database gebruikt, kunt u de DBMS_XA pakket om één sessie toe te staan ​​deel te nemen aan een transactie die bij de eerste sessie is gestart. Zoals Tim Hall aantoont, kunt u een transactie in één sessie starten, aan die transactie deelnemen vanuit een andere sessie en de niet-vastgelegde wijzigingen lezen die in de transactie zijn aangebracht. Helaas zal dat echter niet helpen met sessievariabelen (ervan uitgaande dat "sessievariabele" pakketvariabele betekent die een sessiebereik heeft).

Maak het pakket en de tabel:

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 sessie 1 starten we een globale transactie, stellen de pakketvariabele in en voegen een rij in de tabel in voordat we de globale transactie opschorten (waardoor een andere sessie deze kan hervatten)

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 sessie 2 hervatten we de globale transactie, lezen uit de tabel, lezen de sessievariabele en beëindigen de globale transactie. Merk op dat de query tegen de tabel de rij ziet die we hebben ingevoegd, maar de wijziging van de pakketvariabele is niet zichtbaar.

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.

Om de sessiestatus tussen de sessies te delen, zou het mogelijk zijn om een ​​algemene toepassingscontext in plaats van pakketvariabelen te gebruiken? Je zou dat kunnen combineren met de DBMS_XA pakketten als u zowel databasetabellen als sessiestatus wilt lezen.

Creëer de context en het pakket met de getter en 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;

Stel in sessie 1 de waarde in van de contextvariabele G_VAR tot 47 voor sessie 12345

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

Nu kan sessie 2 de waarde uit de context lezen

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

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



  1. Geef de dag, maand en jaar terug in MySQL

  2. Oracle database herstel

  3. Hoe subquery te gebruiken om Mysql SELECT LIMIT offset te definiëren?

  4. Django kan een onderliggende rij niet toevoegen of bijwerken:een beperking van een externe sleutel mislukt