2012-03-07 22 views
6

Có khả năng kết nối với Oracle (qua OCI) từ một quy trình, sau đó kết nối trên cùng một phiên cơ sở dữ liệu từ một tiến trình khác không?Tôi có thể duy trì một phiên Oracle từ hai máy khách oci không?

Trong ứng dụng hiện tại của tôi, có hai cách để truy cập cơ sở dữ liệu: một đồng bộ và một cách không đồng bộ (bằng cách sử dụng một quy trình riêng biệt, giao tiếp thông qua ổ cắm). Vấn đề là hai phương pháp thực hiện các phiên riêng biệt.

Nếu tôi cố gắng, ví dụ: một bản cập nhật trên một phiên, sau đó cố gắng cập nhật cùng một bảng từ phiên khác mà không cam kết, tôi bị treo trong cuộc gọi OCI.

Tệ hơn nữa, nếu biến phiên được đặt từ một phiên - phiên khác không nhìn thấy nó (đó chính xác là tên của thông báo ...).

Trả lời

6

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 
+0

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

+0

@ 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 đó. –

+0

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

Các vấn đề liên quan