Bạn có thể tạo bảng processes
. Bạn cũng đảm bảo rằng mỗi quy trình có một số loại số nhận dạng duy nhất - ví dụ: mã băm của owner, object_name
từ dba_objects
để bạn có thể tạo mã này theo cách động trong gói của mình.
Sau đó, bạn tạo một hàm thành lock each row individually khi quy trình được chạy.
Vì @Sergio đã chỉ ra trong các nhận xét, điều này sẽ không hoạt động nếu vì một lý do nào đó bạn cần thực hiện ở giữa quá trình - trừ khi, tất nhiên, bạn được chọn lại sau mỗi lần commit.
function locking (Pid) return number is
l_locked number := 0;
begin
select 1
into l_locked
from processes
where id = Pid
-- exit immediately if the proc is running
for update nowait
;
return l_locked;
exception when others then
return 0;
end;
Điều này có lợi cho việc khóa hàng đó trong processes
cho bạn cho đến khi phiên hiện đang chạy thủ tục của bạn kết thúc.
Sau đó, bạn quấn này trong thủ tục của bạn:
-- if we failed to lock locking will have thrown an error
-- i.e. we have 0 here.
if locking(123) = 0 then
exit;
end if;
Chừng nào mỗi thủ tục có một id duy nhất - bit quan trọng - thủ tục của bạn sẽ thoát sạch.
Điều này có thể không áp dụng trong trường hợp của bạn nhưng cách thông thường của tôi là sử dụng mod
. Mặc dù nó không dừng lại 2 của cùng một tiến trình đang chạy nó đảm bảo rằng khi bạn có nhiều hơn 1 bạn chỉ chạy chúng trên các dữ liệu khác nhau. Một cái gì đó như sau:
procedure my_procedure (PNumerator number, PDenominator number) is
cursor c_my_cursor (CNumerator number, CDenominator number) is
select columns
from my_table
where mod(ascii(substr(id, -1)), CDenominator) = CNumerator
;
begin
open c_my_cursor(PNumerator, PDenominator);
...
end;
+1 câu hỏi hay, nhưng 'v $ session' không phải là duy nhất trên mô-đun, hành động để dễ bị sai. – Ben
Xem thêm http://stackoverflow.com/questions/1053484/block-procedure-pl-sql-with-oracle – gavenkoa