2013-04-02 60 views
1

我遇到了一個問題,我的印象是解決方案很簡單,但我無法弄清楚。oracle select&update或在多線程環境中選擇並插入

A有一個多線程環境和一個pl sql存儲過程。 這裏面的過程我有類似的東西:

select * into mycount from toto; 
If mycount >0 then update...; 
else insert ...; 

的問題是,我有很多的線程調用這個程序。 是否有一種簡單的方法一次只有一個線程執行上面的一段代碼? 我知道我可以使用select for update,但因爲我可以有更新或插入我想這不適用於我。

非常感謝。

+0

嘗試在過程調用結束時添加一個提交,以便逐個線程不會保留表上的獨佔DML操作。任何DDL都可能破壞Lock。 –

+0

好主意。謝謝。 –

+0

第一個'select'不是必需的。只需運行'update'並檢查更新的行數。這是零,做插入(這種方式「選擇」將只做一次)。或者使用'MERGE'語句。 –

回答

1

曾經使用過一個FLAG一個單獨的表MODIFY_CHECKER。使用此表&列作爲一種手段,只允許一個線程更新/你的實際表中插入(TOTO我想)

你可以像下面講一下你現有的PL/SQL程序 -

IF (select count(1) from modify_checker where flag = 1) > 0 THEN 
    -- Another thread is already working, so just raise exception 
    RAISE <<exception>> 
ELSE 
    -- No other thread working on this, so go ahead 
    UPDATE modify_checker SET flag = 1; 
    COMMIT; 
    <<actual code to update or insert actual table>> 
    UPDATE modify_checker SET flag = 0; 
    COMMIT; 
END IF; 
1

您想將引入某種在應用層面的中介隊列什麼最簡單的辦法 - 各個線程會發送到隊列,隊列處理器的請求,將讀出隊列的請求,並作出必要的電話給數據庫。

這,在我看來,是你不必改變太多,以得到它的工作最簡單的解決方案。唯一的潛在問題是,如果需要響應,這種解決方案可能會變得複雜 - 如果是這樣,這仍然是一種選擇,但應用程序代碼由於需要處理異步響應而變得複雜了一些。

+0

好主意,但我cannont實現它,因爲我的存儲過程被調用在不同的地方,我不能修改每一塊代碼。 –

+0

你將不得不修改你的代碼以使任何解決方案工作。您無法從SQL服務器執行任何操作。 – CathalMF

+0

另一種選擇是讓當前proc充當「隊列」,然後調用一個新的proc,可能使用類似Oracle AQueues的東西。根據我對AQ的經驗,這可能很麻煩。如果你不想改變客戶端代碼,那麼我認爲沿着這些線路的東西可能是你唯一的選擇 –

0

您可以在您訪問程序時立即放入一個鎖,並在您退出時釋放它。這種方式一次只能有一個人可以訪問。

ALTER TABLE tl_test ENABLE TABLE LOCK;

ALTER TABLE tl_test DISABLE TABLE LOCK;