是否有可能從一個進程連接到Oracle(通過OCI),然後從另一個進程連接到同一個數據庫會話?我可以從兩個oci客戶端維護一個Oracle會話嗎?
在我當前的應用程序中,有兩種訪問數據庫的方式:同步和異步(通過使用單獨的進程,通過套接字進行通信)。 問題是兩種方法實現不同的會話。
如果我嘗試在一個會話上進行更新,然後嘗試從另一個會話更新同一個表而不進行提交,我得到了OCI調用的掛起。
更糟糕的是,如果會話變量是從一個會話設置的 - 其他會話沒有看到它(這正是名稱所說的......)。
是否有可能從一個進程連接到Oracle(通過OCI),然後從另一個進程連接到同一個數據庫會話?我可以從兩個oci客戶端維護一個Oracle會話嗎?
在我當前的應用程序中,有兩種訪問數據庫的方式:同步和異步(通過使用單獨的進程,通過套接字進行通信)。 問題是兩種方法實現不同的會話。
如果我嘗試在一個會話上進行更新,然後嘗試從另一個會話更新同一個表而不進行提交,我得到了OCI調用的掛起。
更糟糕的是,如果會話變量是從一個會話設置的 - 其他會話沒有看到它(這正是名稱所說的......)。
如果您使用的是11g數據庫,則可以使用DBMS_XA
package來允許一個會話加入第一個會話啓動的事務。正如Tim Hall deomonstrates所說,您可以在一個會話中開始一個事務,從另一個會話中加入該事務,並讀取在事務中進行的未提交的更改。然而不幸的是,這不會對會話變量有幫助(假設「會話變量」意味着具有會話範圍的包變量)。
創建包和表:
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;
在第一節,我們啓動一個全局事務,設置包變量,並暫停全局事務前行插入表(允許另一個會話以恢復它)
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.
要共享會話狀態的會話之間,將有可能使用global application context而不是使用包變量?如果要讀取數據庫表和會話狀態,可以將它與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
begin
pkg_foo.set_var(12345, 47);
end;
現在,會話2設定爲47上下文變量G_VAR
的值可以從上下文中讀取值
1* select pkg_foo.get_var(12345) from dual
SQL>/
PKG_FOO.GET_VAR(12345)
----------------------
47
是的,「會話變量」表示包變量可以有會話範圍......所以這種方法不是解決方案。不管怎麼說,還是要謝謝你! – user581243 2012-03-07 15:18:58
@ user581243 - 你有可能使用全局上下文而不是包變量?我用這種可能性更新了我的答案。 – 2012-03-07 15:39:01
再次感謝。這很有趣。不過,我需要在C++代碼層解決這個問題,而不是在pl/sql代碼層。這不是一次性的情況,而是經常發生的事情。對於我們的應用程序來說,C++代碼的修改要比pl/sql代碼少得多,這就是爲什麼我不想將複雜性轉移到pl/sql代碼的原因。 – user581243 2012-03-08 07:54:08