我可以从两个oci客户端维护一个Oracle会话吗
can I maintain one Oracle session from two oci clients?
是否有可能从一个进程连接到Oracle(通过OCI),然后从另一个进程在同一数据库会话上连接?
在我当前的应用程序中,有两种访问数据库的方式:同步方式和异步方式(通过使用单独的进程,通过套接字进行通信)。问题是这两种方法实现不同的会话。
如果我尝试在一个会话上更新,然后尝试在不提交的情况下从另一个会话更新同一个表,我会挂起OCI调用。
更糟糕的是,如果会话变量是从一个会话设置的,那么另一个会话看不到它(这正是名称所说的…)
如果使用11g数据库,可以使用DBMS_XA
包允许一个会话加入第一个会话启动的事务。正如Tim Hall演示的那样,您可以在一个会话中启动一个事务,从另一个会话加入该事务,并读取事务中未提交的更改。然而,不幸的是,这对会话变量没有帮助(假设"会话变量"是指具有会话范围的包变量)。
创建包和表:
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
包结合使用。
使用getter和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;
在会话1中,将会话12345 的上下文变量G_VAR
的值设置为47
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
相关文章:
- 如何创建一个CMake变量,除非显式重写,否则使用默认值
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- 运行同一解决方案的另一个项目的项目
- 挂起和取消挂起一个文件DLL
- 用C++中的一个变量定义一个常量
- 函数向量_指针有不同的原型,我可以构建一个吗
- 在c++中用vector填充一个简单的动态数组
- 如何在选项卡视图Qt中设置一个新项目,并保存以前的项目
- 预处理器:插入结构名称中的前一个行号
- 我在c++代码中生成了一个运行时#3异常
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- 从链接列表c++中删除一个项目
- 告诉一个 const char 数组,除了编译时 C 样式的字符串外,它不以 '