Nếu bạn đang sử dụng cơ sở dữ liệu 11g, bạn có thể sử dụng DBMS_XA
package để cho phép một phiên tham gia giao dịch bắt đầu vào phiên đầu tiên. Như Tim Hall deomonstrates, bạn có thể bắt đầu một giao dịch trong một phiên, tham gia giao dịch đó từ một phiên khác và đọc các thay đổi không được cam kết trong giao dịch. Thật không may, tuy nhiên, đó không phải là sẽ giúp đỡ với các biến phiên (giả sử rằng "biến phiên" có nghĩa là biến gói có phạm vi phiên).
Tạo gói và bảng:
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;
Trong Phần 1, chúng ta bắt đầu một giao dịch toàn cầu, thiết lập biến đóng gói, và chèn một hàng vào bảng trước khi đình chỉ giao dịch toàn cầu (cho phép phiên khác để tiếp tục lại)
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.
Trong phiên 2, chúng tôi tiếp tục giao dịch toàn cầu, đọc từ bảng, đọc biến phiên và kết thúc giao dịch toàn cầu. Lưu ý rằng truy vấn đối với bảng thấy hàng mà chúng tôi đã chèn nhưng thay đổi biến gói không hiển thị.
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.
Để chia sẻ trạng thái phiên giữa các phiên, bạn có thể sử dụng global application context thay vì sử dụng biến gói không? Bạn có thể kết hợp với gói DBMS_XA
nếu bạn muốn đọc cả bảng cơ sở dữ liệu và trạng thái phiên.
Tạo bối cảnh và gói với phương thức getter và 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;
Trong phiên 1, thiết lập giá trị của bối cảnh biến G_VAR
đến 47 cho phiên 12345
begin
pkg_foo.set_var(12345, 47);
end;
Bây giờ, phiên 2 có thể đọc giá trị từ ngữ cảnh
1* select pkg_foo.get_var(12345) from dual
SQL>/
PKG_FOO.GET_VAR(12345)
----------------------
47
có, "biến phiên" có nghĩa là gói var có thể có phạm vi phiên ... vì vậy phương pháp này không phải là giải pháp. dù sao cũng cảm ơn bạn! – user581243
@ user581243 - Bất kỳ cơ hội nào bạn có thể sử dụng ngữ cảnh chung chứ không phải là biến gói? Tôi đã cập nhật câu trả lời của mình với khả năng đó. –
cảm ơn một lần nữa. Điều này rất thú vị. Tuy nhiên tôi cần phải giải quyết điều này ở lớp mã C++, không phải ở lớp mã pl/sql. Nó không phải là một tình huống một lần, đó là một cái gì đó sẽ xảy ra khá thường xuyên. Đối với ứng dụng của chúng tôi, mã C++ được sửa đổi ít hơn nhiều so với mã pl/sql và đây là lý do tại sao tôi không muốn chuyển sự phức tạp sang mã pl/sql. – user581243