Câu trả lời:
Bạn có thể làm điều này với DBMS_LOCK
và một khóa độc quyền.
Xem thủ tục sau đây:
CREATE OR REPLACE PROCEDURE myproc
IS
lockhandle VARCHAR2(128);
retcode NUMBER;
BEGIN
DBMS_LOCK.ALLOCATE_UNIQUE('myproclock',lockhandle);
retcode:=DBMS_LOCK.REQUEST(lockhandle,timeout=>0, lockmode=>DBMS_LOCK.x_mode);
IF retcode<>0
THEN
raise_application_error(-20000,'myproc is already running');
END IF;
/* sleep so that we can test with a 2nd execution */
DBMS_LOCK.sleep(1000);
retcode:=DBMS_LOCK.RELEASE(lockhandle);
END myproc;
/
Kiểm tra (phiên 1):
SQL> BEGIN
2 myproc();
3 END;
4 /
(Rõ ràng trả lại khi DBMS_LOCK.sleep()
trả về).
Kiểm tra (phiên 2):
SQL> BEGIN
2 myproc();
3 END;
4 /
BEGIN
*
ERROR at line 1:
ORA-20000: myproc is already running
ORA-06512: at "PHIL.MYPROC", line 12
ORA-06512: at line 2
SQL>
Rõ ràng bạn cần phải GRANT EXECUTE ON DBMS_LOCK TO YOURUSER;
.
Sử dụng bảng 'khóa'.
Khi thủ tục bắt đầu kiểm tra bảng cho một giá trị đã biết, nếu hiện tại không đi nữa và thoát Proc. Nếu không có, ghi giá trị vào bảng, thực hiện thủ tục, sau đó xóa giá trị và thoát như bình thường.
Khi khách hàng của tôi có một yêu cầu có logic kinh doanh độc đáo như thế này, tôi thử chuyển câu hỏi và hỏi tại sao điều này lại cần thiết.
Cách tốt nhất để đảm bảo chỉ có một bản sao đang chạy là không cho phép người dùng thực hiện quy trình. Nếu quy trình này đặc biệt thì việc sử dụng nên được giới hạn ở dba / nhà phát triển.
Một cách khác là chỉ chạy thủ tục này như một công việc. Thêm một kiểm tra trong thủ tục để xem nếu có bất kỳ công việc gọi này đang chạy. Nếu họ sau đó dừng xử lý thêm và đăng nhập sự xuất hiện.