2015-11-11 76 views
1

請假設我們有一個封裝內的程序:Oracle PL/SQL:如何檢測過程是否已經在運行?

MY_PACKAGE.MY_PROCEDURE 

這個過程可以從許多用戶推出。

如何修改程序,以檢測是否該過程是目前運行,因爲從另一個用戶推出?

什麼是最安全的方法來檢測它?

謝謝你考慮我的要求。

編輯01:「這將取決於爲什麼你需要知道如果一個過程已經運行或不」==>如果該過程目前正在運行,它不會再次啓動。

+0

我可能只是創建一個表,它至少存儲用戶名,包,過程和開始時間,然後更改過程以在調用時將一行插入到表中,然後將其刪除。我期待着看到其他人的建議!嗯,或者,您可以使用dbms_application_info調用來設置模塊和操作,然後可以看到v $ session中每個會話的最新內容。這取決於你爲什麼需要知道一個proc是否已經運行。 – Boneist

+0

@Boneist:我想你還是會有比賽條件。我不知道任何可以在PL/SQL中訪問的同步原語,但我的知識遠非詳盡無遺。 Oracle PL/SQL API的任何地方都有可用的互斥鎖嗎? –

+0

我記得在我以前的工作中有一個人告訴我他們使用了Oracle上下文功能來實現類似的功能。看看這篇文章: http://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_5002.htm 它一定是'全球訪問'的上下文,你可以簡單地把名稱值夫婦爲你想要的所有參數。不幸的是我現在無法嘗試,但這看起來很有前景。另一方面,使用與使用狀態表一樣簡單的解決方案並使用自治事務寫入它會更有意義:) –

回答

3

您可以使用DBMS_APPLICATION_INFO包獲取此類信息。

PROCEDURE MY_PROCEDURE(..) IS 
BEGIN 
DBMS_APPLICATION_INFO.SET_CLIENT_INFO('MY_PACKAGE.MY_PROCEDURE running'); 

    ... All your stuff 

DBMS_APPLICATION_INFO.SET_CLIENT_INFO(NULL); 
EXCEPTION 
    WHEN OTHERS THEN 
    DBMS_APPLICATION_INFO.SET_CLIENT_INFO(NULL); 
    RAISE; 
END MY_PROCEDURE; 

爲了檢查它,你可以選擇V $ session視圖:

SELECT * 
FROM v$session 
WHERE client_info = 'MY_PACKAGE.MY_PROCEDURE running'; 

如果你得到任何記錄,則程序正在運行。

+0

謝謝你的例子代碼。如果我在例外情況下忘記設置NULL,該怎麼辦?從Oracle會話註銷後,是否有任何方法可以重置? – UltraCommit

+1

client_info與會話有關,因此當會話關閉時,client_info當然也會消失。 –

+0

非常感謝您的熱心幫助。 – UltraCommit

2

根據其他人提及的內容以及對DBMS_LOCK包頭的快速瀏覽,可以看出您可以使用各種DBMS_LOCK例程來完成您正在嘗試執行的操作。如果我正確閱讀標題註釋,則想要撥打ALLOCATE_UNIQUE以獲得唯一的指定鎖定的句柄,那麼您將調用REQUEST並將鎖定模式設置爲'x'(獨佔)以嘗試抓取鎖。如果REQUEST調用返回0,則可以繼續並運行例程。完成後,請致電RELEASE使鎖可用於下一個呼叫者。

祝你好運。

+0

您可以添加一些PL/SQL代碼嗎? – UltraCommit

相關問題