Oracle
 sql >> Base de données >  >> RDS >> Oracle

puis-je maintenir une session Oracle à partir de deux clients oci ?

Si vous utilisez une base de données 11g, vous pouvez utiliser le DBMS_XA paquet pour permettre à une session de rejoindre une transaction démarrée par la première session. Comme le montre Tim Hall, vous pouvez démarrer une transaction dans une session, rejoindre cette transaction à partir d'une autre session et lire les modifications non validées apportées à la transaction. Malheureusement, cela ne va pas aider avec les variables de session (en supposant que "variable de session" signifie une variable de package qui a une portée de session).

Créez le package et la table :

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;

Dans la session 1, nous commençons une transaction globale, définissons la variable de package et insérons une ligne dans la table avant de suspendre la transaction globale (ce qui permet à une autre session de la reprendre)

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.

Dans la session 2, nous reprenons la transaction globale, lisons la table, lisons la variable de session et terminons la transaction globale. Notez que la requête sur la table voit la ligne que nous avons insérée mais la modification de la variable de package n'est pas 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.

Pour partager l'état de la session entre les sessions, serait-il possible d'utiliser un contexte d'application global plutôt que d'utiliser des variables de package ? Vous pouvez combiner cela avec le DBMS_XA packages si vous souhaitez lire à la fois les tables de la base de données et l'état de la session.

Créez le contexte et le package avec le getter et le 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;

Dans la session 1, définissez la valeur de la variable de contexte G_VAR à 47 pour la session 12345

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

Maintenant, la session 2 peut lire la valeur du contexte

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

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